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

# List all users with a relationship to an object

> The ListUsers API returns a list of all the users of a specific type that have a relation to a given object.

 To arrive at a result, the API uses:

- An [authorization model](/docs/getting-started/configure-model)

- Explicit tuples written through the Write API

- Contextual tuples present in the request

- Implicit tuples that exist by virtue of applying set theory

For example: `document:2021-budget#viewer@document:2021-budget#viewer`. In this example, the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`.

An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID is used.

> **Note:** We recommend you specify authorization model ID for better performance.

You may also specify `contextual_tuples` that are treated as regular tuples. Each of these tuples may have an associated `condition`.
You may also provide a `context` object used to evaluate the conditioned tuples in the system.

> **Note:** We recommend you provide a value for all the input parameters of all the conditions. This ensures that all tuples be evaluated correctly.

The response contains the related users in an array in the "users" field of the response. These results may include specific objects, usersets 
or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.

In cases where a type-bound public access result is returned (e.g. `user:*`), it cannot be inferred that all subjects
of that type have a relation to the object; it is possible that negations exist and checks should still be queried
on individual subjects to ensure access to that document.
The number of users in the response array are limited by the execution timeout specified in the flag `OPENFGA_LIST_USERS_DEADLINE` and by the upper bound specified in the flag `OPENFGA_LIST_USERS_MAX_RESULTS`, whichever is hit first.
The returned users are not sorted, and therefore two identical calls may yield different sets of users.



## OpenAPI

````yaml https://raw.githubusercontent.com/openfga/api/refs/heads/main/docs/openapiv3/apidocs.openapi.json post /stores/{store_id}/list-users
openapi: 3.0.3
info:
  contact:
    email: community@openfga.dev
    name: OpenFGA
    url: https://openfga.dev
  description: >-
    A high performance and flexible authorization/permission engine built for
    developers and inspired by Google Zanzibar.
  license:
    name: Apache-2.0
    url: https://github.com/openfga/openfga/blob/main/LICENSE
  title: OpenFGA
  version: 1.x
servers: []
security: []
tags:
  - name: AuthZenService
  - name: OpenFGAService
paths:
  /stores/{store_id}/list-users:
    post:
      tags:
        - Relationship Queries
      summary: List all users with a relationship to an object
      description: >-
        The ListUsers API returns a list of all the users of a specific type
        that have a relation to a given object.

         To arrive at a result, the API uses:

        - An [authorization model](/docs/getting-started/configure-model)


        - Explicit tuples written through the Write API


        - Contextual tuples present in the request


        - Implicit tuples that exist by virtue of applying set theory


        For example: `document:2021-budget#viewer@document:2021-budget#viewer`.
        In this example, the set of users who are viewers of
        `document:2021-budget` are the set of users who are the viewers of
        `document:2021-budget`.


        An `authorization_model_id` may be specified in the body. If it is not
        specified, the latest authorization model ID is used.


        > **Note:** We recommend you specify authorization model ID for better
        performance.


        You may also specify `contextual_tuples` that are treated as regular
        tuples. Each of these tuples may have an associated `condition`.

        You may also provide a `context` object used to evaluate the conditioned
        tuples in the system.


        > **Note:** We recommend you provide a value for all the input
        parameters of all the conditions. This ensures that all tuples be
        evaluated correctly.


        The response contains the related users in an array in the "users" field
        of the response. These results may include specific objects, usersets 

        or type-bound public access. Each of these types of results is encoded
        in its own type and not represented as a string.


        In cases where a type-bound public access result is returned (e.g.
        `user:*`), it cannot be inferred that all subjects

        of that type have a relation to the object; it is possible that
        negations exist and checks should still be queried

        on individual subjects to ensure access to that document.

        The number of users in the response array are limited by the execution
        timeout specified in the flag `OPENFGA_LIST_USERS_DEADLINE` and by the
        upper bound specified in the flag `OPENFGA_LIST_USERS_MAX_RESULTS`,
        whichever is hit first.

        The returned users are not sorted, and therefore two identical calls may
        yield different sets of users.
      operationId: ListUsers
      parameters:
        - in: path
          name: store_id
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ListUsersBody'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListUsersResponse'
          description: A successful response.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorMessageResponse'
          description: Request failed due to invalid input.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthenticatedResponse'
          description: Not authenticated.
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenResponse'
          description: Forbidden.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PathUnknownErrorMessageResponse'
          description: Request failed due to incorrect path.
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AbortedMessageResponse'
          description: Request was aborted due a transaction conflict.
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnprocessableContentMessageResponse'
          description: Request timed out due to excessive request throttling.
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalErrorMessageResponse'
          description: Request failed due to internal server error.
      x-codeSamples:
        - lang: node
          label: Node.js
          source: >-
            const { OpenFgaClient, ConsistencyPreference } =
            require('@openfga/sdk');


            const fgaClient = new OpenFgaClient({
              apiUrl: process.env.FGA_API_URL,
              storeId: process.env.FGA_STORE_ID,
              authorizationModelId: process.env.FGA_MODEL_ID, // Optional; requests can override this.
            });


            async function main() {
                const body = {
                  "object": {"type": "document", "id": "budget"},
                  "relation": "reader",
                  "user_filters": [
                    {
                      "type": "user"
                    }
                  ]
                };
                const options = {
                
                };
                const response = await fgaClient.listUsers(body, options);
            }


            main().catch((error) => {
                console.error(error);
                process.exitCode = 1;
            });
        - lang: go
          label: Go
          source: |-
            package main

            import (
                "context"
                "os"

                openfga "github.com/openfga/go-sdk"
                . "github.com/openfga/go-sdk/client"
            )

            func main() {
                fgaClient, err := NewSdkClient(&ClientConfiguration{
                    ApiUrl: os.Getenv("FGA_API_URL"),
                    StoreId: os.Getenv("FGA_STORE_ID"),
                    AuthorizationModelId: os.Getenv("FGA_MODEL_ID"), // Optional; requests can override this.
                })
                if err != nil {
                    panic(err)
                }
                
                body := ClientListUsersRequest{
                  Object: openfga.FgaObject{
                    Type: "document",
                    Id: "budget",
                  },
                  Relation: "reader",
                  UserFilters: []openfga.UserTypeFilter{
                    openfga.UserTypeFilter{
                      Type: "user",
                    },
                  },
                }
                options := ClientListUsersOptions{
                
                }
                data, err := fgaClient.ListUsers(context.Background()).Body(body).Options(options).Execute()
                if err != nil {
                    panic(err)
                }
                _ = data
            }
        - lang: dotnet
          label: .NET
          source: |-
            using System.Collections.Generic;
            using OpenFga.Sdk.Client;
            using OpenFga.Sdk.Client.Model;
            using OpenFga.Sdk.Model;
            using Environment = System.Environment;

            var fgaClient = new OpenFgaClient(new ClientConfiguration() {
              ApiUrl = Environment.GetEnvironmentVariable("FGA_API_URL"),
              StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
              AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"), // Optional; requests can override this.
            });

            var body = new ClientListUsersRequest {
              Object = new FgaObject {
                Type = "document",
                Id = "budget",
              },
              Relation = "reader",
              UserFilters = new List<UserTypeFilter> {
                new UserTypeFilter {
                  Type = "user",
                },
              },
            };
            var options = new ClientListUsersOptions {

            };
            var response = await fgaClient.ListUsers(body, options);
        - lang: python
          label: Python
          source: >-
            import asyncio

            import os

            from openfga_sdk.client import OpenFgaClient, ClientConfiguration

            from openfga_sdk.client.models import ClientTuple

            from openfga_sdk.client.models.list_users_request import
            ClientListUsersRequest

            from openfga_sdk.models import RelationshipCondition, FgaObject,
            UserTypeFilter


            async def main():
                configuration = ClientConfiguration(
                    api_url=os.environ.get("FGA_API_URL"),
                    store_id=os.environ.get("FGA_STORE_ID"),
                    authorization_model_id=os.environ.get("FGA_MODEL_ID"), # Optional; requests can override this.
                )
                async with OpenFgaClient(configuration) as fga_client:
                    body = ClientListUsersRequest(
                      object=FgaObject(
                        type="document",
                        id="budget",
                      ),
                      relation="reader",
                      user_filters=[
                        UserTypeFilter(
                          type="user",
                        )
                      ],
                    )
                    options = {
                    
                    }
                    response = await fga_client.list_users(body, options)

            asyncio.run(main())
        - lang: java
          label: Java
          source: |-
            import dev.openfga.sdk.api.client.OpenFgaClient;
            import dev.openfga.sdk.api.configuration.ClientConfiguration;
            import dev.openfga.sdk.api.configuration.*;
            import dev.openfga.sdk.api.client.model.*;
            import dev.openfga.sdk.api.model.*;
            import java.util.List;
            import java.util.Map;
            import java.util.ArrayList;

            public class Example {
                public static void main(String[] args) throws Exception {
                    var config = new ClientConfiguration()
                        .apiUrl(System.getenv("FGA_API_URL"))
                        .storeId(System.getenv("FGA_STORE_ID"))
                        .authorizationModelId(System.getenv("FGA_MODEL_ID")); // Optional; requests can override this.
                    var fgaClient = new OpenFgaClient(config);
                    
                    var body = new ClientListUsersRequest()
                      ._object(new FgaObject()
                        .type("document")
                        .id("budget"))
                      .relation("reader")
                      .userFilters(java.util.Arrays.asList(new UserTypeFilter()
                        .type("user")));
                    var options = new ClientListUsersOptions();
                    var response = fgaClient.listUsers(body, options).get();
                }
            }
        - lang: bash
          label: curl
          source: >-
            # Set FGA_API_URL to the URL of your OpenFGA server.

            # Set FGA_STORE_ID to your store ID.

            # These examples use a server with authentication disabled.

            # For authenticated servers, see
            /docs/getting-started/setup-sdk-client.


            curl -X POST "$FGA_API_URL/stores/$FGA_STORE_ID/list-users" \
              -H "content-type: application/json" \
              -d '{
              "authorization_model_id": "'"$FGA_MODEL_ID"'",
              "object": {
                "type": "document",
                "id": "budget"
              },
              "relation": "reader",
              "user_filters": [
                {
                  "type": "user"
                }
              ]
            }'
components:
  schemas:
    ListUsersBody:
      properties:
        authorization_model_id:
          example: 01G5JAVJ41T49E9TT3SKVS7X1J
          type: string
        consistency:
          allOf:
            - $ref: '#/components/schemas/ConsistencyPreference'
            - description: >-
                Controls the consistency preference for this request. Default
                value is `UNSPECIFIED`, which has the same behavior as
                `MINIMIZE_LATENCY`.
        context:
          description: >-
            Additional request context used to evaluate any ABAC conditions
            encountered

            in the query evaluation.
          type: object
        contextual_tuples:
          items:
            allOf:
              - $ref: '#/components/schemas/TupleKey'
              - type: object
          maxItems: 100
          type: array
        object:
          allOf:
            - $ref: '#/components/schemas/Object'
            - example: document:example
        relation:
          example: reader
          type: string
        user_filters:
          description: The type of results returned. Only accepts exactly one value.
          example:
            - type: user
            - relation: member
              type: group
          items:
            allOf:
              - $ref: '#/components/schemas/UserTypeFilter'
              - type: object
          maxItems: 1
          minItems: 1
          type: array
      required:
        - object
        - relation
        - user_filters
      type: object
    ListUsersResponse:
      properties:
        users:
          items:
            allOf:
              - $ref: '#/components/schemas/User'
              - type: object
          type: array
      required:
        - users
      type: object
    ValidationErrorMessageResponse:
      example:
        code: validation_error
        message: Generic validation error
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
      type: object
    UnauthenticatedResponse:
      example:
        code: unauthenticated
        message: unauthenticated
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
      type: object
    ForbiddenResponse:
      example:
        code: forbidden
        message: the principal is not authorized to perform the action
      properties:
        code:
          $ref: '#/components/schemas/AuthErrorCode'
        message:
          type: string
      type: object
    PathUnknownErrorMessageResponse:
      example:
        code: undefined_endpoint
        message: Endpoint not enabled
      properties:
        code:
          $ref: '#/components/schemas/NotFoundErrorCode'
        message:
          type: string
      type: object
    AbortedMessageResponse:
      example:
        code: '10'
        message: transaction conflict
      properties:
        code:
          type: string
        message:
          type: string
      type: object
    UnprocessableContentMessageResponse:
      example:
        code: throttled_timeout_error
        message: timeout due to throttling on complex request
      properties:
        code:
          $ref: '#/components/schemas/UnprocessableContentErrorCode'
        message:
          type: string
      type: object
    InternalErrorMessageResponse:
      example:
        code: internal_error
        message: Internal Server Error
      properties:
        code:
          $ref: '#/components/schemas/InternalErrorCode'
        message:
          type: string
      type: object
    ConsistencyPreference:
      default: UNSPECIFIED
      description: |-
        Controls the consistency preferences when calling the query APIs.

         - UNSPECIFIED: Default if not set. Behavior will be the same as MINIMIZE_LATENCY.
         - MINIMIZE_LATENCY: Minimize latency at the potential expense of lower consistency.
         - HIGHER_CONSISTENCY: Prefer higher consistency, at the potential expense of increased latency.
      enum:
        - UNSPECIFIED
        - MINIMIZE_LATENCY
        - HIGHER_CONSISTENCY
      example: MINIMIZE_LATENCY
      type: string
    TupleKey:
      properties:
        condition:
          $ref: '#/components/schemas/RelationshipCondition'
        object:
          example: document:2021-budget
          maxLength: 256
          type: string
        relation:
          example: reader
          maxLength: 50
          type: string
        user:
          example: user:anne
          maxLength: 512
          type: string
      required:
        - user
        - relation
        - object
      type: object
    Object:
      description: |-
        Object represents an OpenFGA Object.

        An Object is composed of a type and identifier (e.g. 'document:1')

        See https://openfga.dev/docs/concepts#what-is-an-object
      properties:
        id:
          example: 0bcdf6fa-a6aa-4730-a8eb-9cf172ff16d9
          type: string
        type:
          example: document
          type: string
      required:
        - type
        - id
      type: object
    UserTypeFilter:
      properties:
        relation:
          example: member
          type: string
        type:
          example: group
          type: string
      required:
        - type
      type: object
    User:
      description: >-
        User.


        Represents any possible value for a user (subject or principal). Can be
        a:

        - Specific user object e.g.: 'user:will', 'folder:marketing',
        'org:contoso', ...)

        - Specific userset (e.g. 'group:engineering#member')

        - Public-typed wildcard (e.g. 'user:*')


        See https://openfga.dev/docs/concepts#what-is-a-user
      properties:
        object:
          $ref: '#/components/schemas/Object'
        userset:
          $ref: '#/components/schemas/UsersetUser'
        wildcard:
          $ref: '#/components/schemas/TypedWildcard'
      type: object
    ErrorCode:
      default: no_error
      enum:
        - no_error
        - validation_error
        - authorization_model_not_found
        - authorization_model_resolution_too_complex
        - invalid_write_input
        - cannot_allow_duplicate_tuples_in_one_request
        - cannot_allow_duplicate_types_in_one_request
        - cannot_allow_multiple_references_to_one_relation
        - invalid_continuation_token
        - invalid_tuple_set
        - invalid_check_input
        - invalid_expand_input
        - unsupported_user_set
        - invalid_object_format
        - write_failed_due_to_invalid_input
        - authorization_model_assertions_not_found
        - latest_authorization_model_not_found
        - type_not_found
        - relation_not_found
        - empty_relation_definition
        - invalid_user
        - invalid_tuple
        - unknown_relation
        - store_id_invalid_length
        - assertions_too_many_items
        - id_too_long
        - authorization_model_id_too_long
        - tuple_key_value_not_specified
        - tuple_keys_too_many_or_too_few_items
        - page_size_invalid
        - param_missing_value
        - difference_base_missing_value
        - subtract_base_missing_value
        - object_too_long
        - relation_too_long
        - type_definitions_too_few_items
        - type_invalid_length
        - type_invalid_pattern
        - relations_too_few_items
        - relations_too_long
        - relations_invalid_pattern
        - object_invalid_pattern
        - query_string_type_continuation_token_mismatch
        - exceeded_entity_limit
        - invalid_contextual_tuple
        - duplicate_contextual_tuple
        - invalid_authorization_model
        - unsupported_schema_version
        - cancelled
        - invalid_start_time
      type: string
    AuthErrorCode:
      default: no_auth_error
      enum:
        - no_auth_error
        - auth_failed_invalid_subject
        - auth_failed_invalid_audience
        - auth_failed_invalid_issuer
        - invalid_claims
        - auth_failed_invalid_bearer_token
        - bearer_token_missing
        - unauthenticated
        - forbidden
      type: string
    NotFoundErrorCode:
      default: no_not_found_error
      enum:
        - no_not_found_error
        - undefined_endpoint
        - store_id_not_found
        - unimplemented
      type: string
    UnprocessableContentErrorCode:
      default: no_throttled_error_code
      enum:
        - no_throttled_error_code
        - throttled_timeout_error
      type: string
    InternalErrorCode:
      default: no_internal_error
      enum:
        - no_internal_error
        - internal_error
        - deadline_exceeded
        - already_exists
        - resource_exhausted
        - failed_precondition
        - aborted
        - out_of_range
        - unavailable
        - data_loss
      type: string
    RelationshipCondition:
      properties:
        context:
          description: >-
            Additional context/data to persist along with the condition.

            The keys must match the parameters defined by the condition, and the
            value types must

            match the parameter type definitions.
          type: object
        name:
          description: >-
            A reference (by name) of the relationship condition defined in the
            authorization model.
          example: condition1
          maxLength: 256
          type: string
      required:
        - name
      type: object
    UsersetUser:
      description: >-
        Userset.


        A set or group of users, represented in the `<type>:<id>#<relation>`
        format


        `group:fga#member` represents all members of group FGA, not to be
        confused by `group:fga` which represents the group itself as a specific
        object.


        See:
        https://openfga.dev/docs/modeling/building-blocks/usersets#what-is-a-userset
      properties:
        id:
          example: fga
          type: string
        relation:
          example: member
          type: string
        type:
          example: group
          type: string
      required:
        - type
        - id
        - relation
      type: object
    TypedWildcard:
      description: >-
        Type bound public access.


        Normally represented using the `<type>:*` syntax


        `employee:*` represents every object of type `employee`, including those
        not currently present in the system


        See https://openfga.dev/docs/concepts#what-is-type-bound-public-access
      properties:
        type:
          example: employee
          type: string
      required:
        - type
      type: object

````