curl --request GET \
--url https://flows.super.ai/api/profile/credential-state \
--header 'Authorization: Bearer <token>'import requests
url = "https://flows.super.ai/api/profile/credential-state"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://flows.super.ai/api/profile/credential-state', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://flows.super.ai/api/profile/credential-state",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://flows.super.ai/api/profile/credential-state"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://flows.super.ai/api/profile/credential-state")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://flows.super.ai/api/profile/credential-state")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"has_password": true,
"is_sso_managed": true
}Whether this account has a password and whether it is SSO-managed
Answer what the account-settings password form may render (FLO-2735 G-2).
Strictly self-scoped: the auth id comes from the caller’s own users row, never
from a parameter, so this cannot be pointed at anybody else. That is what separates
it from the email-keyed get_auth_signin_options_by_email sibling, whose public
endpoint was retired precisely because a caller chose the address it answered for.
Answers 503 when the state cannot be resolved, rather than guessing. An earlier
version failed open to has_password=False, which looked kinder and was worse:
the form then renders “Set a Password” with no current-password field, the submit
omits it, and POST /profile/password — which resolves the same fact from the
same RPC — answers current_password_required, whose copy asks the user to
reload, straight back into the same failing lookup. The most likely trigger is the
deploy window before this revision’s RPC exists. An unknown state is a third
outcome and the form renders a retry for it.
curl --request GET \
--url https://flows.super.ai/api/profile/credential-state \
--header 'Authorization: Bearer <token>'import requests
url = "https://flows.super.ai/api/profile/credential-state"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://flows.super.ai/api/profile/credential-state', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://flows.super.ai/api/profile/credential-state",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://flows.super.ai/api/profile/credential-state"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://flows.super.ai/api/profile/credential-state")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://flows.super.ai/api/profile/credential-state")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"has_password": true,
"is_sso_managed": true
}Authorizations
JWT Bearer token authentication. Include your access token in the Authorization header as: Bearer YOUR_ACCESS_TOKEN
Example:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Response
Credential state resolved
What the account-settings password form is allowed to render (FLO-2735 G-2).
Both fields are read live from auth.users on every call rather than folded
into GET /profile/me. Two reasons: the profile response is fetched on every
page load and this is needed on exactly one screen, and has_password changes
the moment a first password is set — a value cached alongside the profile would
keep showing "Set a password" to someone who just set one.
Whether the Supabase Auth record already has a password. Mirrors the user.HasPassword() guard GoTrue applies before enforcing Require Current Password, so the form asks for a current password exactly when GoTrue would demand one. False for a magic-link-only or freshly invited account, which sets its first password with no current password to give.
Whether the Supabase Auth record is SSO-managed (auth.users.is_sso_user). GoTrue refuses email/phone/password updates for these outright with user_sso_managed, so the form is not rendered at all rather than offered and then rejected. Defaults false so an unknown state still shows a form whose failure is at least explained.