> ## Documentation Index
> Fetch the complete documentation index at: https://developers.askparable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.

## Access

This operation needs a Parable token. An MCP token cannot call it. See [Authentication](/getting-started/authentication.md) for the kinds of token.

Your roles must grant one of `tenant.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.


## OpenAPI

````yaml /api-reference/openapi.json post /api/provider-policies/source-permissions/explain
openapi: 3.0.3
info:
  description: >-
    Use the Workspace API to work with artifacts, connectors, Parables, and
    account resources.
  title: Workspace API
  version: v2026.10.22.1
servers: []
security: []
paths:
  /api/provider-policies/source-permissions/explain:
    post:
      tags:
        - Provider policies
      summary: Explain why one person reads one row under source permissions
      description: >-
        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.
      operationId: ProviderPoliciesExplainSourcePermissionsHandler
      parameters:
        - description: >-
            Workspace slug. Overrides subdomain-based workspace resolution when
            provided.
          in: header
          name: X-Tenant
          required: false
          schema:
            example: acme
            type: string
        - description: Optional request correlation ID echoed back in the response.
          in: header
          name: X-Request-ID
          required: false
          schema:
            example: 550e8400-e29b-41d4-a716-446655440000
            format: uuid
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExplainSourcePermissionsInput'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  data:
                    $ref: '#/components/schemas/WorkspaceSourcePermissionsExplanation'
                  links:
                    $ref: '#/components/schemas/ResponseLinks'
                  meta:
                    $ref: '#/components/schemas/ResponseMeta'
                required:
                  - data
                  - meta
                type: object
          description: Successful response
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '400':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: >-
            The request is not valid. `detail` says why. A value that breaks a
            field rule gives the code `WA-VL-001` and an `errors` member that
            names each field.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '401':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: The token is missing, malformed, revoked, or expired.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '403':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: >-
            The token cannot make this request. For example, the roles of its
            owner do not allow the operation.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '429':
          content:
            text/plain:
              schema:
                example: Too Many Requests
                type: string
          description: >-
            More than 120 requests a minute came from your address. Wait for the
            number of seconds in `Retry-After`, then try again.
          headers:
            Retry-After:
              description: The number of seconds to wait before you try again.
              schema:
                type: integer
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '500':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: The request failed on the server.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
      security:
        - bearerAuth: []
      x-codeSamples:
        - label: TypeScript SDK
          lang: typescript
          source: >-
            import { WebApiSDK } from "@parable-platform/web-api-sdk";

            import type { ExplainSourcePermissionsInput } from
            "@parable-platform/web-api-types";


            const sdk = new WebApiSDK({
              baseUrl: process.env.PARABLE_API_URL!,
              auth: { token: process.env.PARABLE_API_TOKEN! },
              requestInterceptor: (config) => ({
                ...config,
                headers: { ...config.headers, "X-Tenant": process.env.PARABLE_WORKSPACE! },
              }),
            });


            const input: ExplainSourcePermissionsInput = JSON.parse(`{
              "email": "person@example.com",
              "providerKey": "550e8400-e29b-41d4-a716-446655440000",
              "tableKey": "550e8400-e29b-41d4-a716-446655440000",
              "anchorKey": "example"
            }`);

            const result = await sdk.providerPolicies.explainSourcePermissions(
              input
            );
        - label: Python SDK
          lang: python
          source: >-
            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)
        - label: Rust SDK
          lang: rust
          source: >-
            use parable_web_api_sdk::{types, ClientConfig, RequestOptions,
            WebApiSdk};


            let sdk = WebApiSdk::new(ClientConfig::with_base_url(
                std::env::var("PARABLE_API_URL")?,
                Some(std::env::var("PARABLE_API_TOKEN")?),
                None,
            ))?;

            let options = RequestOptions::with_header("X-Tenant",
            std::env::var("PARABLE_WORKSPACE")?, None, None);


            let input: types::ExplainSourcePermissionsInput =
            serde_json::from_value(
                serde_json::json!({
              "email": "person@example.com",
              "providerKey": "550e8400-e29b-41d4-a716-446655440000",
              "tableKey": "550e8400-e29b-41d4-a716-446655440000",
              "anchorKey": "example"
            }),

            )?;

            let result = sdk.provider_policies.explain_source_permissions(
                input,
                Some(&options)
            ).await?;
        - label: Go SDK
          lang: go
          source: "sdk, err := webapisdk.New(webapisdk.SDKConfig{\n\tBaseURL: os.Getenv(\"PARABLE_API_URL\"),\n\tAuth:    &webapisdk.AuthConfig{Token: os.Getenv(\"PARABLE_API_TOKEN\")},\n\tRequestInterceptor: func(ctx context.Context, req *http.Request) error {\n\t\treq.Header.Set(\"X-Tenant\", os.Getenv(\"PARABLE_WORKSPACE\"))\n\t\treturn nil\n\t},\n})\nif err != nil {\n\treturn err\n}\n\nvar input webapitypes.ExplainSourcePermissionsInput\nif 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 {\n\treturn err\n}\nresult, err := sdk.ProviderPoliciesNamespace.ExplainSourcePermissions(ctx, input)"
components:
  schemas:
    ExplainSourcePermissionsInput:
      additionalProperties: false
      description: Asks why one person reads, or does not read, one row of a modeled table.
      properties:
        anchorKey:
          description: The row's value in the table's anchor column.
          maxLength: 4096
          minLength: 1
          type: string
        email:
          description: An email address
          format: email
          maxLength: 255
          pattern: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
          type: string
        providerKey:
          description: UUID v4 with automatic base62 encoding for client-facing APIs
          pattern: >-
            ^([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})$
          type: string
        tableKey:
          description: UUID v4 with automatic base62 encoding for client-facing APIs
          pattern: >-
            ^([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})$
          type: string
      required:
        - email
        - providerKey
        - tableKey
        - anchorKey
      type: object
    WorkspaceSourcePermissionsExplanation:
      properties:
        explanation:
          $ref: '#/components/schemas/SourcePermissionsExplainResponse'
        person:
          $ref: '#/components/schemas/SourcePermissionsPerson'
      required:
        - person
        - explanation
      type: object
    ResponseLinks:
      properties:
        first:
          nullable: true
          type: string
        last:
          nullable: true
          type: string
        next:
          nullable: true
          type: string
        prev:
          nullable: true
          type: string
      type: object
    ResponseMeta:
      properties:
        requestId:
          description: Unique identifier for the request
          type: string
        totalCount:
          description: Total count of items for paginated responses
          nullable: true
          type: integer
      required:
        - requestId
      type: object
    ProblemDetails:
      description: An error response in the Problem Details format (RFC 9457).
      properties:
        code:
          description: The stable error code, when the problem has one.
          example: WA-VL-001
          type: string
        detail:
          description: What went wrong with this request.
          type: string
        details:
          description: >-
            Structured facts about the refusal, such as the entity or the path
            it concerns. Only some refusals have it.
        errors:
          description: >-
            The fields or filters that failed validation. Only a validation or
            filter error has it.
        requestId:
          description: >-
            The ID of the request, when the problem has one. The `X-Request-ID`
            response header always has it.
          type: string
        status:
          description: The HTTP status code.
          example: 400
          type: integer
        title:
          description: A short summary, usually the text of the HTTP status.
          example: Bad Request
          type: string
        type:
          description: >-
            The problem type. It is `about:blank`: the status and `code`
            identify the problem.
          example: about:blank
          type: string
      required:
        - type
        - title
        - status
        - detail
      type: object
    SourcePermissionsExplainResponse:
      properties:
        access:
          description: How source permissions decide the table's rows. Null unless modeled.
          oneOf:
            - $ref: '#/components/schemas/SourcePermissionsTableAccess'
            - enum:
                - null
              nullable: true
              type: string
        accounts:
          description: The person's accounts in the Provider.
          items:
            $ref: '#/components/schemas/SourcePermissionsReaderAccount'
          type: array
        anchorColumn:
          nullable: true
          type: string
        anchorTableKey:
          description: >-
            For an anchored table, its anchor table's key and the column that
            holds

            the anchor key.
          nullable: true
          pattern: >-
            ^([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})$
          type: string
        outcome:
          $ref: '#/components/schemas/SourcePermissionsExplainOutcome'
        refusal:
          description: Why a read would be refused, for `refused`.
          nullable: true
          type: string
        tokens:
          description: |-
            The row's tokens: for an anchored table, the anchor key's tokens in
            anchor_tokens; for an audience table, its audience.
          items:
            $ref: '#/components/schemas/SourcePermissionsRowToken'
          type: array
      required:
        - outcome
        - accounts
        - tokens
      type: object
    SourcePermissionsPerson:
      description: >-
        The person a source permissions preview or explanation is about: an
        active member of the Workspace, found by the email they

        sign in with.
      properties:
        email:
          description: |-
            The email they sign in with, which source permissions match to their
            accounts in each Provider.
          format: email
          maxLength: 255
          pattern: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
          type: string
        userId:
          description: UUID v4 string as base62
          pattern: ^[0-9A-Za-z]{1,22}$
          type: string
      required:
        - userId
        - email
      type: object
    SourcePermissionsTableAccess:
      description: How source permissions decide the rows of one modeled table.
      enum:
        - anchored
        - source_users
        - unrestricted
        - unresolved
      type: string
    SourcePermissionsReaderAccount:
      description: One of the person's source accounts in the table's Provider.
      properties:
        guest:
          type: boolean
        primaryEmail:
          description: An email address
          format: email
          maxLength: 255
          nullable: true
          pattern: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
          type: string
        principalKey:
          type: string
        sourceId:
          type: string
      required:
        - principalKey
        - sourceId
        - guest
      type: object
    SourcePermissionsExplainOutcome:
      enum:
        - readable
        - not_readable
        - not_modeled
        - refused
        - not_served
      type: string
    SourcePermissionsRowToken:
      description: One token that admits readers to the row.
      properties:
        admits:
          description: >-
            Whether the token lets the person read the row: they hold it, and it
            is

            neither expired nor link-only while the setting is off.
          type: boolean
        expiresAt:
          description: >-
            ISO8601 datetime string. Epoch wire values keep this scalar and
            declare x-temporal-format (unix, unix_millis, unix_micros,
            unix_nanos) on the property; the unit is never guessed from digit
            count.
          format: date-time
          nullable: true
          type: string
        grants:
          items:
            $ref: '#/components/schemas/SourcePermissionsTokenGrant'
          type: array
        held:
          description: Whether the person holds the token, and why.
          type: boolean
        holds:
          items:
            $ref: '#/components/schemas/SourcePermissionsHold'
          type: array
        linkOnly:
          description: |-
            Only link-only grants give it: it admits only while the Workspace's
            link-only setting is on.
          type: boolean
        token:
          type: string
      required:
        - token
        - linkOnly
        - held
        - holds
        - admits
        - grants
      type: object
    SourcePermissionsTokenGrant:
      description: One grant behind a token of the row, from providers.access.grants.
      properties:
        cause:
          $ref: '#/components/schemas/AccessGrantCause'
        level:
          $ref: '#/components/schemas/AccessLevel'
        viaKey:
          description: |-
            The row the grant came through, such as the parent of an inherited
            grant. Null when the grant names the row itself.
          nullable: true
          type: string
      required:
        - level
        - cause
      type: object
    SourcePermissionsHold:
      description: One reason a person holds a token.
      properties:
        depth:
          description: |-
            For a membership, the number of membership edges from `via` to the
            token; 1 is direct.
          format: int64
          maximum: 9007199254740991
          minimum: -9007199254740991
          nullable: true
          type: integer
        kind:
          $ref: '#/components/schemas/SourcePermissionsHoldKind'
        through:
          description: >-
            For a membership deeper than 1, the group, team or role `via`
            belongs

            to directly on the way. Null when the projection does not say.
          nullable: true
          type: string
        via:
          description: |-
            The person's token it comes through: the account for an account, a
            domain or `source_users`; the member for a membership. Null for
            everyone.
          nullable: true
          type: string
      required:
        - kind
      type: object
    AccessGrantCause:
      description: Why a grant in providers.access.grants exists.
      enum:
        - direct
        - owner
        - inherited
        - audience
      type: string
    AccessLevel:
      description: >-
        The common level of a grant in providers.access.grants, from

        the most access to the least. x-accessLevel maps each source role to a

        level. A source role that x-accessLevel maps to `none` grants nothing,
        and

        the access job writes no grant row for it.
      enum:
        - owner
        - write
        - comment
        - read
      type: string
    SourcePermissionsHoldKind:
      description: How a person holds a token.
      enum:
        - account
        - membership
        - domain
        - source_users
        - everyone
        - reporting_line
      type: string
  headers:
    X-Request-ID:
      description: >-
        The ID of the request. It is the `X-Request-ID` value that you sent, or
        an ID that the server made. Give it when you report a problem.
      schema:
        type: string
  securitySchemes:
    bearerAuth:
      description: >-
        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.
      scheme: bearer
      type: http

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.