import json
import os
from parable_types_web_api import ExplainSourcePermissionsInput
from parable_web_api_sdk import ClientConfig, WebApiSDK
sdk = WebApiSDK(
ClientConfig(
base_url=os.environ["PARABLE_API_URL"],
auth_token=os.environ["PARABLE_API_TOKEN"],
default_headers={"X-Tenant": os.environ["PARABLE_WORKSPACE"]},
)
)
input_data = ExplainSourcePermissionsInput.model_validate(
json.loads("{\"email\":\"person@example.com\",\"providerKey\":\"550e8400-e29b-41d4-a716-446655440000\",\"tableKey\":\"550e8400-e29b-41d4-a716-446655440000\",\"anchorKey\":\"example\"}"),
)
result = sdk.provider_policies.explain_source_permissions(input_data)sdk, err := webapisdk.New(webapisdk.SDKConfig{
BaseURL: os.Getenv("PARABLE_API_URL"),
Auth: &webapisdk.AuthConfig{Token: os.Getenv("PARABLE_API_TOKEN")},
RequestInterceptor: func(ctx context.Context, req *http.Request) error {
req.Header.Set("X-Tenant", os.Getenv("PARABLE_WORKSPACE"))
return nil
},
})
if err != nil {
return err
}
var input webapitypes.ExplainSourcePermissionsInput
if err := json.Unmarshal([]byte(`{"email":"person@example.com","providerKey":"550e8400-e29b-41d4-a716-446655440000","tableKey":"550e8400-e29b-41d4-a716-446655440000","anchorKey":"example"}`), &input); err != nil {
return err
}
result, err := sdk.ProviderPoliciesNamespace.ExplainSourcePermissions(ctx, input){
"data": {
"explanation": {
"accounts": [
{
"guest": true,
"principalKey": "<string>",
"sourceId": "<string>",
"primaryEmail": "jsmith@example.com"
}
],
"outcome": "readable",
"tokens": [
{
"admits": true,
"grants": [
{
"cause": "direct",
"level": "owner",
"viaKey": "<string>"
}
],
"held": true,
"holds": [
{
"kind": "account",
"depth": 0,
"through": "<string>",
"via": "<string>"
}
],
"linkOnly": true,
"token": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}
],
"access": "anchored",
"anchorColumn": "<string>",
"anchorTableKey": "<string>",
"refusal": "<string>"
},
"person": {
"email": "jsmith@example.com",
"userId": "<string>"
}
},
"meta": {
"requestId": "<string>",
"totalCount": 123
},
"links": {
"first": "<string>",
"last": "<string>",
"next": "<string>",
"prev": "<string>"
}
}{
"detail": "<string>",
"status": 400,
"title": "Bad Request",
"type": "about:blank",
"code": "WA-VL-001",
"details": "<unknown>",
"errors": "<unknown>",
"requestId": "<string>"
}{
"detail": "<string>",
"status": 400,
"title": "Bad Request",
"type": "about:blank",
"code": "WA-VL-001",
"details": "<unknown>",
"errors": "<unknown>",
"requestId": "<string>"
}{
"detail": "<string>",
"status": 400,
"title": "Bad Request",
"type": "about:blank",
"code": "WA-VL-001",
"details": "<unknown>",
"errors": "<unknown>",
"requestId": "<string>"
}Too Many Requests{
"detail": "<string>",
"status": 400,
"title": "Bad Request",
"type": "about:blank",
"code": "WA-VL-001",
"details": "<unknown>",
"errors": "<unknown>",
"requestId": "<string>"
}Explain why one person reads one row under source permissions
For the active member who signs in with the given email and one row of a modeled table, named by its value in the table’s anchor column, returns whether source permissions let that member read the row, each token that admits readers to it with the grants behind it, and, for each token the member holds, how they hold it: their own account, a group, team or role they belong to, a domain, or every user of the Provider. Only someone who reads every row of the table with their own SQL can ask. Each explanation is recorded in the audit trail with the member and the table, never the row.
import json
import os
from parable_types_web_api import ExplainSourcePermissionsInput
from parable_web_api_sdk import ClientConfig, WebApiSDK
sdk = WebApiSDK(
ClientConfig(
base_url=os.environ["PARABLE_API_URL"],
auth_token=os.environ["PARABLE_API_TOKEN"],
default_headers={"X-Tenant": os.environ["PARABLE_WORKSPACE"]},
)
)
input_data = ExplainSourcePermissionsInput.model_validate(
json.loads("{\"email\":\"person@example.com\",\"providerKey\":\"550e8400-e29b-41d4-a716-446655440000\",\"tableKey\":\"550e8400-e29b-41d4-a716-446655440000\",\"anchorKey\":\"example\"}"),
)
result = sdk.provider_policies.explain_source_permissions(input_data)sdk, err := webapisdk.New(webapisdk.SDKConfig{
BaseURL: os.Getenv("PARABLE_API_URL"),
Auth: &webapisdk.AuthConfig{Token: os.Getenv("PARABLE_API_TOKEN")},
RequestInterceptor: func(ctx context.Context, req *http.Request) error {
req.Header.Set("X-Tenant", os.Getenv("PARABLE_WORKSPACE"))
return nil
},
})
if err != nil {
return err
}
var input webapitypes.ExplainSourcePermissionsInput
if err := json.Unmarshal([]byte(`{"email":"person@example.com","providerKey":"550e8400-e29b-41d4-a716-446655440000","tableKey":"550e8400-e29b-41d4-a716-446655440000","anchorKey":"example"}`), &input); err != nil {
return err
}
result, err := sdk.ProviderPoliciesNamespace.ExplainSourcePermissions(ctx, input){
"data": {
"explanation": {
"accounts": [
{
"guest": true,
"principalKey": "<string>",
"sourceId": "<string>",
"primaryEmail": "jsmith@example.com"
}
],
"outcome": "readable",
"tokens": [
{
"admits": true,
"grants": [
{
"cause": "direct",
"level": "owner",
"viaKey": "<string>"
}
],
"held": true,
"holds": [
{
"kind": "account",
"depth": 0,
"through": "<string>",
"via": "<string>"
}
],
"linkOnly": true,
"token": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}
],
"access": "anchored",
"anchorColumn": "<string>",
"anchorTableKey": "<string>",
"refusal": "<string>"
},
"person": {
"email": "jsmith@example.com",
"userId": "<string>"
}
},
"meta": {
"requestId": "<string>",
"totalCount": 123
},
"links": {
"first": "<string>",
"last": "<string>",
"next": "<string>",
"prev": "<string>"
}
}{
"detail": "<string>",
"status": 400,
"title": "Bad Request",
"type": "about:blank",
"code": "WA-VL-001",
"details": "<unknown>",
"errors": "<unknown>",
"requestId": "<string>"
}{
"detail": "<string>",
"status": 400,
"title": "Bad Request",
"type": "about:blank",
"code": "WA-VL-001",
"details": "<unknown>",
"errors": "<unknown>",
"requestId": "<string>"
}{
"detail": "<string>",
"status": 400,
"title": "Bad Request",
"type": "about:blank",
"code": "WA-VL-001",
"details": "<unknown>",
"errors": "<unknown>",
"requestId": "<string>"
}Too Many Requests{
"detail": "<string>",
"status": 400,
"title": "Bad Request",
"type": "about:blank",
"code": "WA-VL-001",
"details": "<unknown>",
"errors": "<unknown>",
"requestId": "<string>"
}Access
This operation needs a Parable token. An MCP token cannot call it. See Authentication for the kinds of token. Your roles must grant one oftenant.providerpolicies.view, tenant.providerpolicies.manage.
Errors
WA-PP-007: Parable could not read the access projection. Try again.WA-PP-011: No active member of the Workspace signs in with this email. Enter the email that a member of this Workspace signs in with.WA-PP-012: An explanation says who can open the table’s rows, and your own Policies narrow the table or your roles do not read it with SQL. Ask someone who reads every row of the table to explain it.
Authorizations
A personal access token, which starts with pat_. A Parable token can call each operation that the roles of its owner allow. An MCP token can call only the read operations that are open to agents. A SQL token does not work on this API.
Headers
Workspace slug. Overrides subdomain-based workspace resolution when provided.
"acme"
Optional request correlation ID echoed back in the response.
"550e8400-e29b-41d4-a716-446655440000"
Body
Asks why one person reads, or does not read, one row of a modeled table.
The row's value in the table's anchor column.
1 - 4096An email address
255^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$UUID v4 with automatic base62 encoding for client-facing APIs
^([0-9A-Za-z]{1,22}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$UUID v4 with automatic base62 encoding for client-facing APIs
^([0-9A-Za-z]{1,22}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$