Read Authority
curl --request GET \
--url https://api.sublay.io/v7/:projectId/workspaces/:id/authority/me \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.sublay.io/v7/:projectId/workspaces/:id/authority/me"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.sublay.io/v7/:projectId/workspaces/:id/authority/me', 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://api.sublay.io/v7/:projectId/workspaces/:id/authority/me",
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://api.sublay.io/v7/:projectId/workspaces/:id/authority/me"
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://api.sublay.io/v7/:projectId/workspaces/:id/authority/me")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sublay.io/v7/:projectId/workspaces/:id/authority/me")
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_bodyWorkspace Endpoints
Read Authority
The resolved standing of a user on a workspace — permissions as a service
Read Authority
curl --request GET \
--url https://api.sublay.io/v7/:projectId/workspaces/:id/authority/me \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.sublay.io/v7/:projectId/workspaces/:id/authority/me"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.sublay.io/v7/:projectId/workspaces/:id/authority/me', 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://api.sublay.io/v7/:projectId/workspaces/:id/authority/me",
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://api.sublay.io/v7/:projectId/workspaces/:id/authority/me"
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://api.sublay.io/v7/:projectId/workspaces/:id/authority/me")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sublay.io/v7/:projectId/workspaces/:id/authority/me")
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_bodyReturns the caller’s resolved standing on a workspace:
A service/master key called this route without naming an
A plain user token sent an
Every path id on the workspaces bundle is checked for UUID shape before the route runs, so a malformed one is a plain
See also: useFetchWorkspaceAuthority · fetchWorkspaceAuthority (node-sdk) · fetchWorkspaceAuthority (js-sdk)
{ reasons, capabilities, permissions, rank }, computed via the authority resolver (fast-path + bounded ancestor climb). This is the endpoint your authorization server reads (via the node SDK) to make its own app-level decisions.
reasons is an array of structured entries — { type, viaWorkspaceId? } — distinguishing owner / ancestor-owner / member / reach-holder, so you always know why a user has what they have and which workspace grants it. It is the same object shape a roster entry’s reasons carries. viaWorkspaceId names the granting ancestor and is present on ancestor-owner / reach-holder only (owner / member are grants on the workspace itself). A user reaching in from several ancestors carries one entry per granting ancestor.
This read is inherently a self read (or a privileged-key read of a named user), so capabilities / permissions / rank are always returned in full here — unlike the member-standing read, which fences them. (The fence exists to stop a caller reconstructing someone else’s rank; there is nobody else in this payload.)
There is no convenience
?permission= check and no can() middleware. Sublay never consumes your opaque permissions, so a permission check is a one-line .includes() on the returned record:const authority = await sublay.workspaces.fetchWorkspaceAuthority({ workspaceId, actingUserId });
if (authority.permissions.includes("deploy")) { /* allow */ }
Path Parameters
string
required
The workspace UUID.
Query Parameters
string
required
Service/master keys only — the user to act as, whose standing is resolved. Required for a key: this route has no unbounded path (there is no such thing as “the app’s standing”), so a key that names nobody is refused with
400 workspace/missing-user-id.A client token omits it — the subject is the token’s own user. The field is not ignored for such a token: sending your own user id is a harmless no-op, but sending anyone else’s is a 403 workspace/unauthorized. See Acting on behalf of a user.Response
{
"reasons": [
{ "type": "member" },
{ "type": "ancestor-owner", "viaWorkspaceId": "ws_root" }
],
"capabilities": ["view", "invite", "remove-member"],
"permissions": ["deploy"],
"rank": 5
}
reasons— structured standings;viaWorkspaceIdis present onancestor-owner/reach-holderonly.capabilities— the fully-resolved set (direct + reach + ownership).viewis implied by every other capability — any user with standing on the workspace resolves withview, including a member whose storedcapabilitiesarray is empty. A user with no relation at all resolves to an empty set.permissions— per-node (the direct membership on this workspace only; may be empty). Does not cascade.rank— the direct-membership rank, ornullfor owners / ancestor-owners / reach-only holders.- There is no
relativeRankon this read. It is an offset from the caller, and here the caller is the subject — so it could only ever be0, a constant dressed as a coordinate.rankis the position this endpoint reports.relativeRankis meaningful on the roster and member-standing reads, where the subject is somebody else.
Error Responses
Missing Acting User — 400
Missing Acting User — 400
{ "error": "Missing user ID", "code": "workspace/missing-user-id" }
actingUserId. The read resolves a user’s standing, so there is nobody to resolve it for.Acted as Another User — 403
Acted as Another User — 403
{ "error": "Unauthorized", "code": "workspace/unauthorized" }
actingUserId naming a different user. Only a service/master key may resolve someone else’s standing.Invalid Path Parameter — 400
Invalid Path Parameter — 400
{ "error": "Invalid workspace id: expected a UUID.", "code": "workspace/invalid-params" }
400 rather than a 500 from the database.
