From 32f70db13d4124da82e903abbd6469b18f5191f0 Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Tue, 17 Feb 2026 09:48:12 -0300 Subject: [PATCH] docs: Update documentation from SDK changes (Jan 22 - Feb 16) (#42874) ## Summary This PR updates documentation based on recent changes across multiple SDK repositories since the last run on 2026-01-22. ## Changes Analyzed | SDK | Repository | Commits | Latest Tag | |-----|-----------|---------|------------| | **js** | supabase/supabase-js | 40 | v2.95.4-canary.2 | | **dart** | supabase/supabase-flutter | 4 | - | | **py** | supabase/supabase-py | 12 | v2.28.0 | | **swift** | supabase/supabase-swift | 14 | v2.41.1 | | **kt** | supabase-community/supabase-kt | 36 | 3.3.0 | | **csharp** | supabase-community/supabase-csharp | 1 | v1.1.2 | ## Documentation Updates ### JavaScript SDK (`supabase_js_v2.yml`) - Added optional `jwt` parameter documentation to `mfa.getAuthenticatorAssuranceLevel()` - Added `timeout` and `urlLengthLimit` options to `PostgrestClient` constructor with example ### Kotlin SDK (`supabase_kt_v3.yml`) - Added new `getClaims()` API section with description, parameters, and 3 examples - Added `channel` parameter to OTP `signInWith` config for WhatsApp support - Added WhatsApp OTP sign-in example ### Python SDK (`supabase_py_v2.yml`) - Added `from_.list_v2()` method documentation with cursor-based pagination support - Includes `SearchV2Options` parameter documentation and pagination example - Added note about new User model fields (`is_sso_user`, `deleted_at`, `banned_until`) on `get_user` ### Swift SDK (`supabase_swift_v2.yml`) - Added breaking change note for `mfa.unenroll()`: response now uses `id` instead of `factorId` (since v2.41.1) ### Phone Login Guide (`phone-login.mdx`) - Added Kotlin WhatsApp OTP example to the sign-in section ### SDKs with no documentation updates needed - **Dart**: Only CI and realtime type-cast fix (no user-facing API changes) - **C#**: Only README badge fix ## Test plan - [ ] Verify YAML spec files parse correctly - [ ] Review rendered documentation for new sections - [ ] Confirm code examples match actual SDK APIs --- Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 --- apps/docs/content/guides/auth/phone-login.mdx | 9 ++ apps/docs/spec/supabase_js_v2.yml | 27 +++++ apps/docs/spec/supabase_kt_v3.yml | 63 ++++++++++ apps/docs/spec/supabase_py_v2.yml | 108 ++++++++++++++++++ apps/docs/spec/supabase_swift_v2.yml | 3 + 5 files changed, 210 insertions(+) diff --git a/apps/docs/content/guides/auth/phone-login.mdx b/apps/docs/content/guides/auth/phone-login.mdx index fab354ef5a2..b817093423c 100644 --- a/apps/docs/content/guides/auth/phone-login.mdx +++ b/apps/docs/content/guides/auth/phone-login.mdx @@ -77,6 +77,15 @@ supabase.auth.signInWith(OTP) { } ``` +To send the OTP via WhatsApp instead of SMS (requires Twilio or Twilio Verify provider): + +```kotlin +supabase.auth.signInWith(OTP) { + phone = "+13334445555" + channel = Phone.Channel.WHATSAPP +} +``` + <$Show if="sdk:python"> diff --git a/apps/docs/spec/supabase_js_v2.yml b/apps/docs/spec/supabase_js_v2.yml index fe4f0bc8383..738682fe13c 100644 --- a/apps/docs/spec/supabase_js_v2.yml +++ b/apps/docs/spec/supabase_js_v2.yml @@ -2590,6 +2590,12 @@ functions: - Authenticator Assurance Level (AAL) is the measure of the strength of an authentication mechanism. - In Supabase, having an AAL of `aal1` refers to having the 1st factor of authentication such as an email and password or OAuth sign-in while `aal2` refers to the 2nd factor of authentication such as a time-based, one-time-password (TOTP) or Phone factor. - If the user has a verified factor, the `nextLevel` field will return `aal2`, else, it will return `aal1`. + - An optional `jwt` parameter can be passed to check the AAL level of a specific JWT instead of the current session. + params: + - name: jwt + isOptional: true + type: string + description: An optional JWT to check the AAL level for. If not provided, the current session's JWT is used. examples: - id: get-aal name: Get the AAL details of a session @@ -2615,6 +2621,12 @@ functions: error: null } ``` + - id: get-aal-with-jwt + name: Get the AAL details for a specific JWT + code: | + ```js + const { data, error } = await supabase.auth.mfa.getAuthenticatorAssuranceLevel(jwt) + ``` - id: admin-api title: 'Overview' notes: | @@ -7724,6 +7736,9 @@ functions: - id: postgrest-js-postgrestclient-constructor title: new PostgrestClient() $ref: '@supabase/postgrest-js.PostgrestClient.constructor' + notes: | + - A `timeout` option (in milliseconds) can be set to automatically abort requests that take too long. + - A `urlLengthLimit` option (default: 8000) can be set to control when URL length warnings are included in error messages for aborted requests. examples: - id: postgrest-js-postgrestclient-constructor-example-1 name: Example 1 @@ -7736,6 +7751,18 @@ functions: schema: 'public', }) ``` + - id: postgrest-js-postgrestclient-constructor-with-timeout + name: With timeout + code: |- + ```ts + import PostgrestClient from '@supabase/postgrest-js' + + const postgrest = new PostgrestClient('https://xyzcompany.supabase.co/rest/v1', { + headers: { apikey: 'public-anon-key' }, + schema: 'public', + timeout: 30000, // 30 second timeout + }) + ``` - id: postgrest-js-postgrestclient-from title: PostgrestClient.from() $ref: '@supabase/postgrest-js.PostgrestClient.from' diff --git a/apps/docs/spec/supabase_kt_v3.yml b/apps/docs/spec/supabase_kt_v3.yml index 54092d4247e..228e3759c0a 100644 --- a/apps/docs/spec/supabase_kt_v3.yml +++ b/apps/docs/spec/supabase_kt_v3.yml @@ -3160,6 +3160,10 @@ functions: isOptional: true type: String? description: The captcha token when having captcha enabled. + - name: channel + isOptional: true + type: Phone.Channel? + description: The channel to send the OTP to when using phone sign-in. Defaults to SMS. Set to `Phone.Channel.WHATSAPP` for WhatsApp delivery. examples: - id: sign-in-with-email name: Sign in with email @@ -3181,6 +3185,17 @@ functions: phone = "+4912345679" } ``` + - id: sign-in-with-whatsapp-otp + name: Sign in with WhatsApp OTP + isSpotlight: false + description: The user will be sent a WhatsApp message which contains an OTP. Requires a Twilio or Twilio Verify provider to be configured. + code: | + ```kotlin + supabase.auth.signInWith(OTP) { + phone = "+4912345679" + channel = Phone.Channel.WHATSAPP + } + ``` - id: sign-in-with-oauth title: 'signInWith(OAuthProvider)' $ref: '@supabase/gotrue-js.GoTrueClient.signInWithOAuth' @@ -4055,6 +4070,54 @@ functions: //flow variant, automatically emitting new values on session changes val statusFlow = supabase.auth.mfa.statusFlow ``` + - id: get-claims + title: 'getClaims()' + description: | + Extracts the JWT claims from the access token by first verifying the JWT against the server's JSON Web Key Set (JWKS) endpoint. + notes: | + - Prefer this method over `retrieveUser()` as JWKS responses are cached, resulting in significantly faster responses. + - If the project is not using an asymmetric JWT signing key (like ECC or RSA), it sends a request to the Auth server (similar to `retrieveUser()`) to verify the JWT. + - Returns a `ClaimsResponse` containing `claims` (a `JwtPayload` with typed accessors for standard JWT fields), `header`, and `signature`. + - Standard claims available on `JwtPayload`: `iss`, `sub`, `aud`, `exp`, `iat`, `role`, `aal`, `sessionId`, `email`, `phone`, `isAnonymous`, `amr`, `appMetadata`, `userMetadata`. + - Use `claims.getClaim(key)` or `claims.getClaimOrNull(key)` for custom claims. + params: + - name: jwt + isOptional: true + type: String? + description: An optional specific JWT to verify. If not provided, uses the current session's access token. + - name: options + isOptional: true + type: ClaimsRequestBuilder.() -> Unit + description: Options to customize the behavior, such as allowing expired tokens. + subContent: + - name: allowExpired + isOptional: true + type: Boolean + description: Whether to allow expired JWTs. Defaults to `false`. + examples: + - id: get-claims-basic + name: Get claims from current session + isSpotlight: true + code: | + ```kotlin + val response = supabase.auth.getClaims() + val email = response.claims.email + val role = response.claims.role + val aal = response.claims.aal + ``` + - id: get-claims-custom + name: Get a custom claim + code: | + ```kotlin + val response = supabase.auth.getClaims() + val customValue = response.claims.getClaimOrNull("my_custom_claim") + ``` + - id: get-claims-specific-jwt + name: Verify a specific JWT + code: | + ```kotlin + val response = supabase.auth.getClaims(jwt = "your-jwt-token") + ``` - id: admin-api title: 'Overview' notes: | diff --git a/apps/docs/spec/supabase_py_v2.yml b/apps/docs/spec/supabase_py_v2.yml index 0e0f3410959..3172bbb02d7 100644 --- a/apps/docs/spec/supabase_py_v2.yml +++ b/apps/docs/spec/supabase_py_v2.yml @@ -1232,6 +1232,7 @@ functions: notes: | - This method fetches the user object from the database instead of local session. - This method is useful for checking if the user is authorized because it validates the user's access token JWT on the server. + - The User model includes the following fields (since v2.28.0): `is_sso_user` (bool, defaults to `False`), `deleted_at` (optional string), and `banned_until` (optional string) in addition to the existing fields. examples: - id: get-the-logged-in-user-with-the-current-existing-session name: Get the logged in user with the current existing session @@ -8478,6 +8479,113 @@ functions: ) ``` + - id: from-list-v2 + title: 'from_.list_v2()' + description: | + Lists files within a bucket using cursor-based pagination. Returns separate lists for folders and objects along with pagination metadata. + notes: | + - This method provides cursor-based pagination, which is more efficient for large result sets compared to offset-based pagination in `from_.list()`. + - The response separates folders and objects into distinct lists. + - Use the `nextCursor` field from the response to paginate through results. + - RLS policy permissions required: + - `buckets` table permissions: none + - `objects` table permissions: `select` + - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works + params: + - name: options + isOptional: true + type: SearchV2Options + subContent: + - name: limit + isOptional: true + type: number + description: The maximum number of results to return. + - name: prefix + isOptional: true + type: string + description: Filter results to only objects with keys starting with this prefix. + - name: cursor + isOptional: true + type: string + description: The cursor for pagination, obtained from the `nextCursor` field of a previous response. + - name: with_delimiter + isOptional: true + type: bool + description: Whether to use delimiter-based folder grouping. + - name: sortBy + isOptional: true + type: SortByV2 + description: The column to sort by. + subContent: + - name: column + isOptional: true + type: '"name" | "updated_at" | "created_at"' + - name: order + isOptional: true + type: '"asc" | "desc"' + examples: + - id: list-files-v2 + name: List files with cursor-based pagination + code: | + ```python + response = ( + supabase.storage + .from_("avatars") + .list_v2({"limit": 100, "prefix": "folder/"}) + ) + + print(response.objects) # List of file objects + print(response.folders) # List of folders + print(response.hasNext) # Whether more results exist + print(response.nextCursor) # Use for next page + ``` + response: | + ```json + { + "hasNext": true, + "nextCursor": "eyJrZXkiOiJmb2xkZXIvYXZhdGFyMi5wbmcifQ==", + "folders": [ + { + "key": "folder/subfolder/", + "name": "subfolder" + } + ], + "objects": [ + { + "id": "e668cf7f-821b-4a2f-9dce-7dfa5dd1cfd2", + "name": "avatar1.png", + "key": "folder/avatar1.png", + "updated_at": "2024-05-22T23:06:05.580Z", + "created_at": "2024-05-22T23:04:34.443Z", + "metadata": { + "eTag": "\"c5e8c553235d9af30ef4f6e280790b92\"", + "size": 32175, + "mimetype": "image/png" + } + } + ] + } + ``` + - id: paginate-files-v2 + name: Paginate through all files + code: | + ```python + all_objects = [] + cursor = None + + while True: + options = {"limit": 100} + if cursor: + options["cursor"] = cursor + + response = supabase.storage.from_("avatars").list_v2(options) + all_objects.extend(response.objects) + + if not response.hasNext: + break + cursor = response.nextCursor + ``` + - id: analytics-buckets title: 'Overview' notes: | diff --git a/apps/docs/spec/supabase_swift_v2.yml b/apps/docs/spec/supabase_swift_v2.yml index fb56458bf51..21c302bda5e 100644 --- a/apps/docs/spec/supabase_swift_v2.yml +++ b/apps/docs/spec/supabase_swift_v2.yml @@ -1286,6 +1286,8 @@ functions: ``` - id: mfa-unenroll title: 'mfa.unenroll()' + notes: | + - Since v2.41.1, the unenroll response uses `id` instead of `factorId` to match the server response format. If upgrading from an earlier version, update your code to use `response.id`. examples: - id: unenroll-a-factor name: Unenroll a factor @@ -1297,6 +1299,7 @@ functions: factorId: "34e770dd-9ff9-416c-87fa-43b31d7ef225" ) ) + print(response.id) // ID of the unenrolled factor ``` - id: mfa-get-authenticator-assurance-level title: 'mfa.getAuthenticatorAssuranceLevel()'