Skip to content
C# Reference v1.0

C# Client Library

supabaseView on GitHub

This reference documents every object and method available in Supabase's C# library, supabase. You can use Supabase to interact with your Postgres database, listen to database changes, invoke Deno Edge Functions, build login and user management functionality, and manage large files.


Installing

Install from NuGet#

You can install Supabase package from nuget.org

1
dotnet add package supabase

Enable Data API access#

supabase-csharp uses the Data API to query and mutate your Postgres data. You first need to grant Data API roles permissions to access your tables and functions.

In the Integrations > Data API section of the Dashboard, expose the specific tables and functions you want to access. To automatically grant access for new tables and functions in public, enable Default privileges for new entities.

Alternatively, use SQL to grant the required permissions:

1
-- Before granting access to client roles, make sure RLS is enabled
2
-- and create the policies required for each role's allowed operations.
3
alter table public.your_table enable row level security;
4
-- create policy ... on public.your_table ...;
5
6
-- Grant least-privilege access to tables after RLS and policies are in place
7
grant select on public.your_table to anon;
8
grant select, insert, update, delete on public.your_table to authenticated;
9
grant all on public.your_table to service_role;
10
11
-- Grant execute on functions after verifying any table access they rely on
12
grant execute on function public.your_function to authenticated, service_role;

Initializing

Initializing a new client is pretty straightforward. Find your project url and public key from the admin panel and pass it into your client initialization function.

Supabase is heavily dependent on Models deriving from BaseModel. To interact with the API, one must have the associated model (see example) specified.

Leverage Table, PrimaryKey, and Column attributes to specify names of classes/properties that are different from their C# Versions.

1
var url = Environment.GetEnvironmentVariable("SUPABASE_URL");
2
var key = Environment.GetEnvironmentVariable("SUPABASE_KEY");
3
4
var options = new Supabase.SupabaseOptions
5
{
6
AutoConnectRealtime = true
7
};
8
9
var supabase = new Supabase.Client(url, key, options);
10
await supabase.InitializeAsync();

Fetch data

Performs vertical filtering with SELECT.

  • LINQ expressions do not currently support parsing embedded resource columns. For these cases, string will need to be used.
  • When using string Column Names to select, they must match names in database, not names specified on model properties.
  • Additional information on modeling + querying Joins and Inner Joins can be found in the postgrest-csharp README
  • By default, Supabase projects will return a maximum of 1,000 rows. This setting can be changed in Project API Settings. It's recommended that you keep it low to limit the payload size of accidental or malicious requests. You can use range() queries to paginate through your data.
  • From() can be combined with Modifiers
  • From() can be combined with Filters
  • If using the Supabase hosted platform apikey is technically a reserved keyword, since the API gateway will pluck it out for authentication. It should be avoided as a column name.
1
// Given the following Model (City.cs)
2
[Table("cities")]
3
class City : BaseModel
4
{
5
[PrimaryKey("id")]
6
public int Id { get; set; }
7
8
[Column("name")]
9
public string Name { get; set; }
10
11
[Column("country_id")]
12
public int CountryId { get; set; }
13
14
//... etc.
15
}
16
17
// A result can be fetched like so.
18
var result = await supabase.From<City>().Get();
19
var cities = result.Models

Insert data

Performs an INSERT into the table.

1
[Table("cities")]
2
class City : BaseModel
3
{
4
[PrimaryKey("id", false)]
5
public int Id { get; set; }
6
7
[Column("name")]
8
public string Name { get; set; }
9
10
[Column("country_id")]
11
public int CountryId { get; set; }
12
}
13
14
var model = new City
15
{
16
Name = "The Shire",
17
CountryId = 554
18
};
19
20
await supabase.From<City>().Insert(model);

Update data

Performs an UPDATE on the table.

  • Update() is typically called using a model as an argument or from a hydrated model.
1
var update = await supabase
2
.From<City>()
3
.Where(x => x.Name == "Auckland")
4
.Set(x => x.Name, "Middle Earth")
5
.Update();

Upsert data

Performs an UPSERT into the table.

  • Primary keys should be included in the data payload in order for an update to work correctly.
  • Primary keys must be natural, not surrogate. There are however, workarounds for surrogate primary keys.
1
var model = new City
2
{
3
Id = 554,
4
Name = "Middle Earth"
5
};
6
7
await supabase.From<City>().Upsert(model);

Delete data

Performs a DELETE on the table.

  • Delete() should always be combined with Filters to target the item(s) you wish to delete.
1
await supabase
2
.From<City>()
3
.Where(x => x.Id == 342)
4
.Delete();

Call a Postgres function

You can call functions as a "Remote Procedure Call".

That's a fancy way of saying that you can put some logic into your database then call it from anywhere. It's especially useful when the logic rarely changes - like password resets and updates.

1
await supabase.Rpc("hello_world", null);

Using filters

Filters allow you to only return rows that match certain conditions.

Filters can be used on Select(), Update(), and Delete() queries.

Note: LINQ expressions do not currently support parsing embedded resource columns. For these cases, string will need to be used.

1
var result = await supabase.From<City>()
2
.Select(x => new object[] { x.Name, x.CountryId })
3
.Where(x => x.Name == "The Shire")
4
.Single();

Column is equal to a value

Finds all rows whose value on the stated column exactly matches the specified value.

1
var result = await supabase.From<City>()
2
.Where(x => x.Name == "Bali")
3
.Get();

Column is not equal to a value

Finds all rows whose value on the stated column doesn't match the specified value.

1
var result = await supabase.From<City>()
2
.Select(x => new object[] { x.Name, x.CountryId })
3
.Where(x => x.Name != "Bali")
4
.Get();

Column is greater than a value

Finds all rows whose value on the stated column is greater than the specified value.

1
var result = await supabase.From<City>()
2
.Select(x => new object[] { x.Name, x.CountryId })
3
.Where(x => x.CountryId > 250)
4
.Get();

Column is greater than or equal to a value

Finds all rows whose value on the stated column is greater than or equal to the specified value.

1
var result = await supabase.From<City>()
2
.Select(x => new object[] { x.Name, x.CountryId })
3
.Where(x => x.CountryId >= 250)
4
.Get();

Column is less than a value

Finds all rows whose value on the stated column is less than the specified value.

1
var result = await supabase.From<City>()
2
.Select("name, country_id")
3
.Where(x => x.CountryId < 250)
4
.Get();

Column is less than or equal to a value

Finds all rows whose value on the stated column is less than or equal to the specified value.

1
var result = await supabase.From<City>()
2
.Where(x => x.CountryId <= 250)
3
.Get();

Column matches a pattern

Finds all rows whose value in the stated column matches the supplied pattern (case sensitive).

1
var result = await supabase.From<City>()
2
.Filter(x => x.Name, Operator.Like, "%la%")
3
.Get();

Column matches a case-insensitive pattern

Finds all rows whose value in the stated column matches the supplied pattern (case insensitive).

1
await supabase.From<City>()
2
.Filter(x => x.Name, Operator.ILike, "%la%")
3
.Get();

Column is a value

A check for exact equality (null, true, false), finds all rows whose value on the stated column exactly match the specified value.

1
var result = await supabase.From<City>()
2
.Where(x => x.Name == null)
3
.Get();

Column is in an array

Finds all rows whose value on the stated column is found on the specified values.

1
var result = await supabase.From<City>()
2
.Filter(x => x.Name, Operator.In, new List<object> { "Rio de Janiero", "San Francisco" })
3
.Get();

Column contains every element in a value

1
var result = await supabase.From<City>()
2
.Filter(x => x.MainExports, Operator.Contains, new List<object> { "oil", "fish" })
3
.Get();

Contained by value

1
var result = await supabase.From<City>()
2
.Filter(x => x.MainExports, Operator.ContainedIn, new List<object> { "oil", "fish" })
3
.Get();

Match a string

Finds all rows whose tsvector value on the stated column matches to_tsquery(query).


Match an associated value

  • Finds a model given a class (useful when hydrating models and correlating with database)
  • Finds all rows whose columns match the specified Dictionary<string, string> object.
1
var city = new City
2
{
3
Id = 224,
4
Name = "Atlanta"
5
};
6
7
var model = supabase.From<City>().Match(city).Single();

Don't match the filter

Finds all rows which doesn't satisfy the filter.

1
var result = await supabase.From<Country>()
2
.Select(x => new object[] { x.Name, x.CountryId })
3
.Where(x => x.Name != "Paris")
4
.Get();

Match at least one filter

Finds all rows satisfying at least one of the filters.

1
var result = await supabase.From<Country>()
2
.Where(x => x.Id == 20 || x.Id == 30)
3
.Get();

Using modifiers

Filters work on the row level—they allow you to return rows that only match certain conditions without changing the shape of the rows. Modifiers are everything that don't fit that definition—allowing you to change the format of the response (e.g., setting a limit or offset).


Order the results

Orders the result with the specified column.

1
var result = await supabase.From<City>()
2
.Select(x => new object[] { x.Name, x.CountryId })
3
.Order(x => x.Id, Ordering.Descending)
4
.Get();

Limit the number of rows returned

Limits the result with the specified count.

1
var result = await supabase.From<City>()
2
.Select(x => new object[] { x.Name, x.CountryId })
3
.Limit(10)
4
.Get();

Limit the query to a range

Limits the result to rows within the specified range, inclusive.

1
var result = await supabase.From<City>()
2
.Select("name, country_id")
3
.Range(0, 3)
4
.Get();

Retrieve one row of data

Retrieves only one row from the result. Result must be one row (e.g. using limit), otherwise this will result in an error.

1
var result = await supabase.From<City>()
2
.Select(x => new object[] { x.Name, x.CountryId })
3
.Single();

Create a new user

Creates a new user.

  • By default, the user needs to verify their email address before logging in. To turn this off, disable Confirm email in your project.
  • Confirm email determines if users need to confirm their email address after signing up.
    • If Confirm email is enabled, a user is returned but session is null.
    • If Confirm email is disabled, both a user and a session are returned.
  • When the user confirms their email address, they are redirected to the SITE_URL by default. You can modify your SITE_URL or add additional redirect URLs in your project.
  • If SignUp() is called for an existing confirmed user:
    • When both Confirm email and Confirm phone (even when phone provider is disabled) are enabled in your project, an obfuscated/fake user object is returned.
    • When either Confirm email or Confirm phone (even when phone provider is disabled) is disabled, the error message, User already registered is returned.
1
var session = await supabase.Auth.SignUp(email, password);

Listen to auth events

Receive a notification every time an auth event happens.

  • Types of auth events: AuthState.SignedIn, AuthState.SignedOut, AuthState.UserUpdated, AuthState.PasswordRecovery, AuthState.TokenRefreshed
1
supabase.Auth.AddStateChangedListener((sender, changed) =>
2
{
3
switch (changed)
4
{
5
case AuthState.SignedIn:
6
break;
7
case AuthState.SignedOut:
8
break;
9
case AuthState.UserUpdated:
10
break;
11
case AuthState.PasswordRecovery:
12
break;
13
case AuthState.TokenRefreshed:
14
break;
15
}
16
});

Create an anonymous user

Creates a new anonymous user.

  • Returns an anonymous user with a session. The user's IsAnonymous claim is set to true.
  • You can later convert an anonymous user into a permanent one by calling UpdateUser() with an email or phone number, or by linking an OAuth identity with LinkIdentity().
  • Enable anonymous sign-ins in your project's auth settings.
1
var session = await supabase.Auth.SignInAnonymously();

Sign in a user

Log in an existing user using email or phone number with password.

  • Requires either an email and password or a phone number and password.
1
var session = await supabase.Auth.SignIn(email, password);

Sign in with ID token (native sign-in)

Signs in a user using an ID token issued by a supported OIDC provider.

  • The ID token is verified for validity before a session is established.
  • Supported providers are Provider.Google, Provider.Apple, Provider.Azure, and Provider.Facebook.
  • If the ID token contains an at_hash claim, pass the matching accessToken. If it contains a nonce claim, pass the nonce used to obtain the token.
1
var session = await supabase.Auth.SignInWithIdToken(Provider.Google, idToken);

Sign in a user through OTP

  • Requires either an email or phone number.
  • This method is used for passwordless sign-ins where a OTP is sent to the user's email or phone number.
  • If you're using an email, you can configure whether you want the user to receive a magiclink or a OTP.
  • If you're using phone, you can configure whether you want the user to receive a OTP.
  • The magic link's destination URL is determined by the SITE_URL. You can modify the SITE_URL or add additional redirect urls in your project.
1
var options = new SignInOptions { RedirectTo = "http://myredirect.example" };
2
var didSendMagicLink = await supabase.Auth.SendMagicLink("joseph@supabase.io", options);

Sign in a user through OAuth

Signs the user in using third party OAuth providers.

  • This method is used for signing in using a third-party provider.
  • Supabase supports many different third-party providers.
1
var signInUrl = supabase.Auth.SignIn(Provider.Github);

Sign in a user through SSO

Signs in a user through enterprise single sign-on (SSO).

  • Before you can use SSO, register your identity provider with the Supabase CLI.
  • You can sign in either by email domain or by the provider's ID (a Guid).
  • The call returns a URL. Redirect the user to it to complete sign-in with their identity provider.
1
var response = await supabase.Auth.SignInWithSSO("acme.com");
2
3
// Redirect the user to complete sign-in.
4
var ssoUrl = response.Uri;

Sign out a user

Signs out the current user, if there is a logged in user.

  • In order to use the SignOut() method, the user needs to be signed in first.
1
await supabase.Auth.SignOut();

Send a password reset request

Sends a reset request to an email address.

Sends a password reset request to an email address. When the user clicks the reset link in the email they are redirected back to your application. Prompt the user for a new password and call Auth.UpdateUser():

1
await supabase.Auth.ResetPasswordForEmail("joseph@supabase.io");

Verify and log in through OTP

  • The VerifyOtp method takes in different verification types. If a phone number is used, the type can either be sms or phone_change. If an email address is used, the type can be one of the following: signup, magiclink, recovery, invite or email_change.
  • The verification type used should be determined based on the corresponding auth method called before VerifyOtp to sign up / sign-in a user.
1
var session = await supabase.Auth.VerifyOTP("+13334445555", TOKEN, MobileOtpType.SMS);

Retrieve a session

Returns the session data, if there is an active session.

1
var session = supabase.Auth.CurrentSession;

Retrieve a new session

Refreshes the current session and returns the new session data.

  • Requires a signed-in user.
  • The SDK refreshes tokens automatically in the background. Call this only when you need to force a refresh.
1
var session = await supabase.Auth.RefreshSession();

Retrieve a user

Returns the user data, if there is a logged in user.


Update a user

Updates user data, if there is a logged in user.

  • In order to use the UpdateUser() method, the user needs to be signed in first.
  • By Default, email updates sends a confirmation link to both the user's current and new email. To only send a confirmation link to the user's new email, disable Secure email change in your project's email auth provider settings.
1
var attrs = new UserAttributes { Email = "new-email@example.com" };
2
var response = await supabase.Auth.Update(attrs);

Link an identity to a user

Links an OAuth identity to the signed-in user.

  • Requires a signed-in user, and uses the PKCE flow.
  • Enable manual linking in your project before using this method.
  • The call returns a URL. Redirect the user to it to authorize the new identity.

Unlink an identity from a user

Unlinks an identity from the signed-in user.

  • Requires a signed-in user with more than one linked identity.
  • Once unlinked, the user can no longer sign in with that identity.
  • Retrieve the user's identities from supabase.Auth.CurrentUser.Identities.

Send a password reauthentication nonce

Sends a reauthentication nonce to the signed-in user's email or phone number.

1
await supabase.Auth.Reauthenticate();

Exchange an auth code for a session

Exchanges an auth code for a session as part of the PKCE flow.

  • Used to complete a PKCE sign-in flow (for example after an OAuth redirect or a password reset).
  • Pass the code verifier you generated at the start of the flow along with the auth code returned in the redirect.
1
var session = await supabase.Auth.ExchangeCodeForSession(codeVerifier, authCode);

Invokes a Supabase Edge Function.

Invokes a Supabase Function. See the guide for details on writing Functions.

  • Requires an Authorization header.
  • Invoke params generally match the Fetch API spec.
1
var options = new InvokeFunctionOptions
2
{
3
Headers = new Dictionary<string, string> {{ "Authorization", "Bearer 1234" }},
4
Body = new Dictionary<string, object> { { "foo", "bar" } }
5
};
6
7
await supabase.Functions.Invoke("hello", options: options);

Subscribe to channel

Subscribe to realtime changes in your database.

  • Realtime is disabled by default for new Projects for better database performance and security. You can turn it on by managing replication.
  • If you want to receive the "previous" data for updates and deletes, you will need to set REPLICA IDENTITY to FULL, like this: ALTER TABLE your_table REPLICA IDENTITY FULL;
1
class CursorBroadcast : BaseBroadcast
2
{
3
[JsonProperty("cursorX")]
4
public int CursorX {get; set;}
5
6
[JsonProperty("cursorY")]
7
public int CursorY {get; set;}
8
}
9
10
var channel = supabase.Realtime.Channel("any");
11
var broadcast = channel.Register<CursorBroadcast>();
12
broadcast.AddBroadcastEventHandler((sender, baseBroadcast) =>
13
{
14
var response = broadcast.Current();
15
});
16
17
await channel.Subscribe();
18
19
// Send a broadcast
20
await broadcast.Send("cursor", new CursorBroadcast { CursorX = 123, CursorY = 456 });

Unsubscribe from a channel

Unsubscribes and removes Realtime channel from Realtime client.

  • Removing a channel is a great way to maintain the performance of your project's Realtime service as well as your database if you're listening to Postgres changes. Supabase will automatically handle cleanup 30 seconds after a client is disconnected, but unused channels may cause degradation as more clients are simultaneously subscribed.
1
var channel = await supabase.From<City>().On(ListenType.All, (sender, change) => { });
2
channel.Unsubscribe();
3
4
// OR
5
6
var channel = supabase.Realtime.Channel("realtime", "public", "*");
7
channel.Unsubscribe()

Retrieve all channels

Returns all Realtime channels.

1
var channels = supabase.Realtime.Subscriptions;

File Buckets

This section contains methods for working with File Buckets.


List all buckets

Retrieves the details of all Storage buckets within an existing product.

  • Policy permissions required:
    • buckets permissions: select
    • objects permissions: none
1
var buckets = await supabase.Storage.ListBuckets();

Retrieve a bucket

Retrieves the details of an existing Storage bucket.

  • Policy permissions required:
    • buckets permissions: select
    • objects permissions: none
1
var bucket = await supabase.Storage.GetBucket("avatars");

Create a bucket

Creates a new Storage bucket

  • Policy permissions required:
    • buckets permissions: insert
    • objects permissions: none
1
var bucket = await supabase.Storage.CreateBucket("avatars");

Empty a bucket

Removes all objects inside a single bucket.

  • Policy permissions required:
    • buckets permissions: select
    • objects permissions: select and delete
1
var bucket = await supabase.Storage.EmptyBucket("avatars");

Update a bucket

Updates a new Storage bucket

  • Policy permissions required:
    • buckets permissions: update
    • objects permissions: none
1
var bucket = await supabase.Storage.UpdateBucket("avatars", new BucketUpsertOptions { Public = false });

Delete a bucket

Deletes an existing bucket. A bucket can't be deleted with existing objects inside it. You must first empty() the bucket.

  • Policy permissions required:
    • buckets permissions: select and delete
    • objects permissions: none
1
var result = await supabase.Storage.DeleteBucket("avatars");

Upload a file

Uploads a file to an existing bucket.

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: insert
1
var imagePath = Path.Combine("Assets", "fancy-avatar.png");
2
3
await supabase.Storage
4
.From("avatars")
5
.Upload(imagePath, "fancy-avatar.png", new FileOptions { CacheControl = "3600", Upsert = false });

Replace an existing file

Replaces an existing file at the specified path with a new one.

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: update and select
1
var imagePath = Path.Combine("Assets", "fancy-avatar.png");
2
await supabase.Storage.From("avatars").Update(imagePath, "fancy-avatar.png");

Move an existing file

Moves an existing file, optionally renaming it at the same time.

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: update and select
1
await supabase.Storage.From("avatars")
2
.Move("public/fancy-avatar.png", "private/fancy-avatar.png");

Copy an existing file

Copies an existing file to a new path in the same bucket.

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: select and insert
1
await supabase.Storage.From("avatars")
2
.Copy("public/fancy-avatar.png", "public/fancy-avatar-copy.png");

Create a signed URL

Create signed url to download file without requiring permissions. This URL can be valid for a set number of seconds.

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: select
1
var url = await supabase.Storage.From("avatars").CreateSignedUrl("public/fancy-avatar.png", 60);

Create signed URLs

Creates signed URLs for multiple files at once. Each URL can be used to download a file without requiring permissions, and is valid for a set number of seconds.

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: select
1
var paths = new List<string> { "public/fancy-avatar.png", "public/fancy-avatar-2.png" };
2
var urls = await supabase.Storage.From("avatars").CreateSignedUrls(paths, 60);

Create signed upload URL

Creates a signed URL that can be used to upload a file without requiring a logged-in user. This is useful for handing off uploads to an untrusted client.

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: insert
  • Pair this with UploadToSignedUrl() to perform the upload.
1
var signedUrl = await supabase.Storage.From("avatars").CreateUploadSignedUrl("fancy-avatar.png");

Upload to a signed URL

Uploads a file to a signed URL created with CreateUploadSignedUrl().

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: insert
1
var imagePath = Path.Combine("Assets", "fancy-avatar.png");
2
var signedUrl = await supabase.Storage.From("avatars").CreateUploadSignedUrl("fancy-avatar.png");
3
4
await supabase.Storage.From("avatars").UploadToSignedUrl(imagePath, signedUrl);

Retrieve public URL

Retrieve URLs for assets in public buckets

  • The bucket needs to be set to public, either via UpdateBucket() or by going to Storage on supabase.com/dashboard, clicking the overflow menu on a bucket and choosing "Make public"
  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: none
1
var publicUrl = supabase.Storage.From("avatars").GetPublicUrl("public/fancy-avatar.png");

Download a file

Downloads a file.

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: select
1
var bytes = await supabase.Storage.From("avatars").Download("public/fancy-avatar.png");

Delete files in a bucket

Deletes files within the same bucket

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: delete and select
1
await supabase.Storage.From("avatars").Remove(new List<string> { "public/fancy-avatar.png" });

List all files in a bucket

Lists all the files within a bucket.

  • Policy permissions required:
    • buckets permissions: none
    • objects permissions: select
1
var objects = await supabase.Storage.From("avatars").List();

Release Notes

1.5.0 - 2026-07-30#

  • Update dependency: Supabase.Realtime@7.3.1
    • Fix channel.Send() hanging on unacknowledged broadcast pushes (#72).
  • Update dependency: Supabase.Storage@2.6.0
    • Add a CancellationToken to the Download methods (#49).
    • Implement cache purge (#50).
    • Non-JSON Storage errors now throw a SupabaseStorageException (#46).
    • Fix a trailing ? being left on CreateSignedUrl results (#51).

1.4.0 - 2026-07-23#

This is the observability release: every child library now emits diagnostics through System.Diagnostics, making the SDK compatible with OpenTelemetry.

  • Expose aggregated telemetry source names for OpenTelemetry (#285).
  • Update dependency: Supabase.Core@1.2.0
    • Add OpenTelemetry-compatible diagnostics primitives (#6).
  • Update dependency: Supabase.Gotrue@6.2.0
    • Emit observability via System.Diagnostics and deprecate the debug callback (#140).
  • Update dependency: Supabase.Postgrest@4.4.0
    • Emit observability via System.Diagnostics and deprecate the debug callback (#136).
  • Update dependency: Supabase.Storage@2.5.0
    • Emit observability via System.Diagnostics (#43).
  • Update dependency: Supabase.Functions@2.2.0
    • Emit observability via System.Diagnostics (#15).

1.3.0 - 2026-07-20#

  • Wire Realtime's Postgrest client automatically so models received from postgres_changes support Update() and Delete() (#282).
  • Update dependency: Supabase.Postgrest@4.3.0
    • Add Client.Attach<T>() to populate a model's client context for Update/Delete (#135).
    • Add ClientOptions.SerializeEnumsAsStrings to opt into string enum serialization (#134).
    • Fix: exclude reference columns from update and delete select queries (#132).
  • Update dependency: Supabase.Realtime@7.3.0
    • Attach the Postgrest client context to models returned by PostgresChangesResponse (#70).

1.2.0 - 2026-07-16#

  • Lower the Newtonsoft.Json minimum version to 13.0.2 across all packages to ease dependency resolution (#275).
  • Update dependency: Supabase.Gotrue@6.1.0
    • Add an option for setting redirect_url on MagicLink sign-in.
    • Add state parameter support to OAuth provider sign-in.
    • Expose RefreshToken(accessToken, refreshToken) on IGotrueClient.
    • Fix: correct the PKCE verifier/challenge swap in SignInWithOtp and ResetPasswordForEmail.
    • Fix: classify refresh-token rejections coming from current gotrue.
  • Update dependency: Supabase.Postgrest@4.2.0
    • Fix: null-reference crash when a Where predicate null-checks a captured value (#122).
    • Fix: preserve DateTime kind, precision, and wall-clock across read and write (#123).
  • Update dependency: Supabase.Storage@2.4.2
    • Add resumable uploads (#29).
    • Add CancellationToken support to upload methods (#30).
    • In-memory caching for resumable uploads (#35).
  • Update dependency: Supabase.Core@1.1.0
    • Add structured X-Client-Info header metadata (#2).
  • Update dependencies: Supabase.Realtime@7.2.1, Supabase.Functions@2.1.1 (maintenance).

1.1.2 - 2025-07-07#

  • Update dependency: Supabase.Realtime@7.2.0
    • Implement Postgres change filters (#55).
    • Fix: SerializerSettings were not being passed to PostgresChangesResponse.
    • Fix: use a compatible websocket library for Blazor WASM.
  • Update dependency: Supabase.Postgrest@4.1.0
    • Add count to ModeledResponse (#103).
    • Add support for long, DateTime, and DateTimeOffset criteria in filter expressions (#101).

1.1.1 - 2024-07-27#

  • Support for passing Headers specified in ClientOptions to the Supabase.Realtime Client.
  • Update dependency: Supabase.Gotrue@6.0.3
  • Update dependency: Supabase.Realtime@7.0.2
    • Updates dependency: Websocket.Client@5.1.2.
    • Updates dependency: Supabase.Postgrest@4.0.3.
    • Adds support for specifying GetHeaders on the RealtimeClient, which are included on the initial request to establish the websocket connection (#167).

1.1.0 - 2024-07-25#

  • Supports passing Headers specified in ClientOptions to child APIs.
  • Drop support for netstandard2.0Supabase now targets netstandard2.1.
  • Update dependency: Supabase.Gotrue@6.0.2
    • Add support for MFA signup and login flows (#103). Huge thanks to @michaelschattgen.
    • Add ExchangeCodeForSession to StatelessClient (#102). Thanks @alexbakker.
    • Major: change target framework to netstandard2.1; use a CSPRNG to generate the code verifier (#99). Thanks @alexbakker.
    • Ban user functionality (#101). Thanks @celestebyte.

1.0.5 - 2024-06-29#

  • Update dependency: Supabase.Storage@2.0.2
  • Update dependency: Supabase.Gotrue@5.0.6
    • Introduces VerifyTokenHash to support the PKCE flow for email signup (#98). Thanks @alexbakker.

1.0.4 - 2024-06-11#

  • Update dependency: Supabase.Gotrue@5.0.5
    • Allow for scoped SignOut. Thanks @AndrewKahr.
    • Various minor SSO fixes. Thanks @Rycko1.
    • Implement SignInWithSSO. Huge thank you to @Rycko1.
  • Update dependency: Supabase.Postgrest@4.0.3

1.0.3 - 2024-05-22#

  • Update dependency: Supabase.Gotrue@5.0.2
    • Add missing properties (ProviderRefreshToken and ProviderToken) to the Session object to reflect the current state of auth-js.
  • Update dependency: Supabase.Realtime@7.0.1
    • Return a Task from the Track and Untrack methods (#47).

1.0.2 - 2024-05-16#

  • Update dependency: Supabase.Postgrest@4.0.2
    • Set ConfigureAwait(false) on the response to prevent deadlocking applications (#96). Thanks @pur3extreme.
  • Update dependency: Supabase.Gotrue@5.0.1
    • Set ConfigureAwait(false) on the response to prevent deadlocking applications.
  • Update dependency: Supabase.Storage@2.0.1

1.0.1 - 2024-05-07#

  • Update dependency: Supabase.Postgrest@4.0.1
    • Changes the IPostgrestTable<> contract to return the interface rather than a concrete type (#92).

1.0.0 - 2024-04-21#

  • Assembly Name has been changed to Supabase.dll
  • Update dependency: postgrest-csharp@5.0.0
    • [MAJOR] Moves namespaces from Postgrest to Supabase.Postgrest
    • Re: #135 Update nuget package name postgrest-csharp to Supabase.Postgrest
  • Update dependency: gotrue-csharp@5.0.0
    • Re: #135 Update nuget package name gotrue-csharp to Supabase.Gotrue
    • Re: #89, Only add access_token to request body when it is explicitly declared.
    • [MINOR] Re: #89 Update signature for SignInWithIdToken which adds an optional accessToken parameter, update doc comments, and call DestroySession in method
    • Re: #88, Add IsAnonymous property to User
    • Re: #90 Implement LinkIdentity and UnlinkIdentity
  • Update dependency: realtime-csharp@7.0.0
    • Merges #45 - Updating the Websocket.Client@5.1.1
    • Re: #135 Update nuget package name realtime-csharp to Supabase.Realtime
  • Update dependency: storage-csharp@2.0.0
    • Re: #135 Update nuget package name storage-csharp to Supabase.Storage
  • Update dependency: functions-csharp@2.0.0
    • Re: #135 Update nuget package name functions-csharp to Supabase.Functions
  • Update dependency: core-csharp@1.0.0
    • Re: #135 Update nuget package name supabase-core to Supabase.Core
  • Adds comments to the remaining undocumented code.