{"id":19100232,"url":"https://github.com/openfga/dotnet-sdk","last_synced_at":"2025-04-18T17:33:05.080Z","repository":{"id":38042675,"uuid":"482957554","full_name":"openfga/dotnet-sdk","owner":"openfga","description":"OpenFGA SDK for .NET - https://www.nuget.org/packages/OpenFga.Sdk","archived":false,"fork":false,"pushed_at":"2024-04-06T03:03:43.000Z","size":618,"stargazers_count":38,"open_issues_count":3,"forks_count":3,"subscribers_count":13,"default_branch":"main","last_synced_at":"2024-04-14T15:07:36.020Z","etag":null,"topics":["access-control","authorization","fga","fine-grained-authorization","openfga","security","zanzibar"],"latest_commit_sha":null,"homepage":"https://openfga.dev","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openfga.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-18T18:40:44.000Z","updated_at":"2024-04-30T01:52:12.792Z","dependencies_parsed_at":"2024-04-30T01:52:07.838Z","dependency_job_id":"2d7a0b4b-cc16-4947-94ec-80cfc5c0f0a0","html_url":"https://github.com/openfga/dotnet-sdk","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfga%2Fdotnet-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfga%2Fdotnet-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfga%2Fdotnet-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfga%2Fdotnet-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openfga","download_url":"https://codeload.github.com/openfga/dotnet-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223783092,"owners_count":17201903,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["access-control","authorization","fga","fine-grained-authorization","openfga","security","zanzibar"],"created_at":"2024-11-09T03:52:37.440Z","updated_at":"2024-11-09T03:53:22.358Z","avatar_url":"https://github.com/openfga.png","language":"C#","funding_links":[],"categories":["security","Developer Ecosystem","hacktoberfest"],"sub_categories":[],"readme":"# .NET SDK for OpenFGA\n\n[![Nuget](https://img.shields.io/nuget/v/OpenFga.Sdk?label=OpenFga.Sdk\u0026style=flat-square)](https://www.nuget.org/packages/OpenFga.Sdk)\n[![Release](https://img.shields.io/github/v/release/openfga/dotnet-sdk?sort=semver\u0026color=green)](https://github.com/openfga/dotnet-sdk/releases)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](./LICENSE)\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fopenfga%2Fdotnet-sdk.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fopenfga%2Fdotnet-sdk?ref=badge_shield)\n[![Join our community](https://img.shields.io/badge/slack-cncf_%23openfga-40abb8.svg?logo=slack)](https://openfga.dev/community)\n[![Twitter](https://img.shields.io/twitter/follow/openfga?color=%23179CF0\u0026logo=twitter\u0026style=flat-square \"@openfga on Twitter\")](https://twitter.com/openfga)\n\nThis is an autogenerated SDK for OpenFGA. It provides a wrapper around the [OpenFGA API definition](https://openfga.dev/api).\n\n## Table of Contents\n\n- [About OpenFGA](#about)\n- [Resources](#resources)\n- [Installation](#installation)\n- [Getting Started](#getting-started)\n  - [Initializing the API Client](#initializing-the-api-client)\n  - [Get your Store ID](#get-your-store-id)\n  - [Calling the API](#calling-the-api)\n    - [Stores](#stores)\n      - [List All Stores](#list-stores)\n      - [Create a Store](#create-store)\n      - [Get a Store](#get-store)\n      - [Delete a Store](#delete-store)\n    - [Authorization Models](#authorization-models)\n      - [Read Authorization Models](#read-authorization-models)\n      - [Write Authorization Model](#write-authorization-model)\n      - [Read a Single Authorization Model](#read-a-single-authorization-model)\n      - [Read the Latest Authorization Model](#read-the-latest-authorization-model)\n    - [Relationship Tuples](#relationship-tuples)\n      - [Read Relationship Tuple Changes (Watch)](#read-relationship-tuple-changes-watch)\n      - [Read Relationship Tuples](#read-relationship-tuples)\n      - [Write (Create and Delete) Relationship Tuples](#write-create-and-delete-relationship-tuples)\n    - [Relationship Queries](#relationship-queries)\n      - [Check](#check)\n      - [Batch Check](#batch-check)\n      - [Expand](#expand)\n      - [List Objects](#list-objects)\n      - [List Relations](#list-relations)\n      - [List Users](#list-users)\n    - [Assertions](#assertions)\n      - [Read Assertions](#read-assertions)\n      - [Write Assertions](#write-assertions)\n  - [Retries](#retries)\n  - [API Endpoints](#api-endpoints)\n  - [Models](#models)\n  - [OpenTelemetry](#opentelemetry)\n- [Contributing](#contributing)\n  - [Issues](#issues)\n  - [Pull Requests](#pull-requests)\n- [License](#license)\n\n## About\n\n[OpenFGA](https://openfga.dev) is an open source Fine-Grained Authorization solution inspired by [Google's Zanzibar paper](https://research.google/pubs/pub48190/). It was created by the FGA team at [Auth0](https://auth0.com) based on [Auth0 Fine-Grained Authorization (FGA)](https://fga.dev), available under [a permissive license (Apache-2)](https://github.com/openfga/rfcs/blob/main/LICENSE) and welcomes community contributions.\n\nOpenFGA is designed to make it easy for application builders to model their permission layer, and to add and integrate fine-grained authorization into their applications. OpenFGA’s design is optimized for reliability and low latency at a high scale.\n\n\n## Resources\n\n- [OpenFGA Documentation](https://openfga.dev/docs)\n- [OpenFGA API Documentation](https://openfga.dev/api/service)\n- [Twitter](https://twitter.com/openfga)\n- [OpenFGA Community](https://openfga.dev/community)\n- [Zanzibar Academy](https://zanzibar.academy)\n- [Google's Zanzibar Paper (2019)](https://research.google/pubs/pub48190/)\n\n## Installation\n\nThe OpenFGA .NET SDK is available on [NuGet](https://www.nuget.org/).\n\nYou can install it using:\n\n* The [dotnet CLI](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli)\n```powershell\ndotnet add package OpenFga.Sdk\n```\n\n* The [Package Manager Console](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell) inside Visual Studio:\n\n```powershell\nInstall-Package OpenFga.Sdk\n```\n\n* [Visual Studio](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-visual-studio), [Visual Studio for Mac](https://docs.microsoft.com/en-us/visualstudio/mac/nuget-walkthrough) and [IntelliJ Rider](https://www.jetbrains.com/help/rider/Using_NuGet.html)\n\nSearch for and install `OpenFga.Sdk` in each of their respective package manager UIs.\n\n\n## Getting Started\n\n### Initializing the API Client\n\n[Learn how to initialize your SDK](https://openfga.dev/docs/getting-started/setup-sdk-client)\n\nWe strongly recommend you initialize the `OpenFgaClient` only once and then re-use it throughout your app, otherwise you will incur the cost of having to re-initialize multiple times or at every request, the cost of reduced connection pooling and re-use, and would be particularly costly in the client credentials flow, as that flow will be preformed on every request.\n\n\u003e The `OpenFga.SdkClient` will by default retry API requests up to 15 times on 429 and 5xx errors.\n\n#### No Credentials\n\n```csharp\nusing OpenFga.Sdk.Client;\nusing OpenFga.Sdk.Client.Model;\nusing OpenFga.Sdk.Model;\n\nnamespace Example {\n    public class Example {\n        public static async Task Main() {\n            try {\n                var configuration = new ClientConfiguration() {\n                    ApiUrl = Environment.GetEnvironmentVariable(\"FGA_API_URL\") ?? \"http://localhost:8080\", // required, e.g. https://api.fga.example\n                    StoreId = Environment.GetEnvironmentVariable(\"FGA_STORE_ID\"), // not needed when calling `CreateStore` or `ListStores`\n                    AuthorizationModelId = Environment.GetEnvironmentVariable(\"FGA_MODEL_ID\"), // Optional, can be overridden per request\n                };\n                var fgaClient = new OpenFgaClient(configuration);\n                var response = await fgaClient.ReadAuthorizationModels();\n            } catch (ApiException e) {\n                 Debug.Print(\"Error: \"+ e);\n            }\n        }\n    }\n}\n```\n\n#### API Token\n\n```csharp\nusing OpenFga.Sdk.Client;\nusing OpenFga.Sdk.Client.Model;\nusing OpenFga.Sdk.Model;\n\nnamespace Example {\n    public class Example {\n        public static async Task Main() {\n            try {\n                var configuration = new ClientConfiguration() {\n                    ApiUrl = Environment.GetEnvironmentVariable(\"FGA_API_URL\") ?? \"http://localhost:8080\", // required, e.g. https://api.fga.example\n                    StoreId = Environment.GetEnvironmentVariable(\"FGA_STORE_ID\"), // not needed when calling `CreateStore` or `ListStores`\n                    AuthorizationModelId = Environment.GetEnvironmentVariable(\"FGA_MODEL_ID\"), // Optional, can be overridden per request\n                    Credentials = new Credentials() {\n                        Method = CredentialsMethod.ApiToken,\n                        Config = new CredentialsConfig() {\n                            ApiToken = Environment.GetEnvironmentVariable(\"FGA_API_TOKEN\"),  // will be passed as the \"Authorization: Bearer ${ApiToken}\" request header\n                        }\n                    }\n                };\n                var fgaClient = new OpenFgaClient(configuration);\n                var response = await fgaClient.ReadAuthorizationModels();\n            } catch (ApiException e) {\n                 Debug.Print(\"Error: \"+ e);\n            }\n        }\n    }\n}\n```\n\n#### Client Credentials\n\n```csharp\nusing OpenFga.Sdk.Client;\nusing OpenFga.Sdk.Client.Model;\nusing OpenFga.Sdk.Model;\n\nnamespace Example {\n    public class Example {\n        public static async Task Main() {\n            try {\n                var configuration = new ClientConfiguration() {\n                    ApiUrl = Environment.GetEnvironmentVariable(\"FGA_API_URL\") ?? \"http://localhost:8080\", // required, e.g. https://api.fga.example\n                    StoreId = Environment.GetEnvironmentVariable(\"FGA_STORE_ID\"), // not needed when calling `CreateStore` or `ListStores`\n                    AuthorizationModelId = Environment.GetEnvironmentVariable(\"FGA_MODEL_ID\"), // Optional, can be overridden per request\n                    Credentials = new Credentials() {\n                        Method = CredentialsMethod.ClientCredentials,\n                        Config = new CredentialsConfig() {\n                            ApiTokenIssuer = Environment.GetEnvironmentVariable(\"FGA_API_TOKEN_ISSUER\"),\n                            ApiAudience = Environment.GetEnvironmentVariable(\"FGA_API_AUDIENCE\"),\n                            ClientId = Environment.GetEnvironmentVariable(\"FGA_CLIENT_ID\"),\n                            ClientSecret = Environment.GetEnvironmentVariable(\"FGA_CLIENT_SECRET\"),\n                        }\n                    }\n                };\n                var fgaClient = new OpenFgaClient(configuration);\n                var response = await fgaClient.ReadAuthorizationModels();\n            } catch (ApiException e) {\n                 Debug.Print(\"Error: \"+ e);\n            }\n        }\n    }\n}\n```\n\n\n### Get your Store ID\n\nYou need your store id to call the OpenFGA API (unless it is to call the [CreateStore](#create-store) or [ListStores](#list-stores) methods).\n\nIf your server is configured with [authentication enabled](https://openfga.dev/docs/getting-started/setup-openfga#configuring-authentication), you also need to have your credentials ready.\n\n### Calling the API\n\n#### Stores\n\n##### List Stores\n\nGet a paginated list of stores.\n\n[API Documentation](https://openfga.dev/api/service#/Stores/ListStores)\n\n```csharp\nvar options = new ClientListStoresOptions {\n    PageSize = 10,\n    ContinuationToken = \"...\",\n};\nvar response = await fgaClient.ListStores(options);\n\n// stores = [{ \"id\": \"01FQH7V8BEG3GPQW93KTRFR8JB\", \"name\": \"FGA Demo Store\", \"created_at\": \"2022-01-01T00:00:00.000Z\", \"updated_at\": \"2022-01-01T00:00:00.000Z\" }]\n```\n\n##### Create Store\n\nInitialize a store.\n\n[API Documentation](https://openfga.dev/api/service#/Stores/CreateStore)\n\n```csharp\nvar store = await fgaClient.CreateStore(new ClientCreateStoreRequest(){Name = \"FGA Demo\"})\n\n// store.Id = \"01FQH7V8BEG3GPQW93KTRFR8JB\"\n\n// store store.Id in database\n\n// update the storeId of the current instance\nfgaClient.StoreId = storeId;\n\n// continue calling the API normally\n```\n\n##### Get Store\n\nGet information about the current store.\n\n[API Documentation](https://openfga.dev/api/service#/Stores/GetStore)\n\n\u003e Requires a client initialized with a storeId\n\n```csharp\nvar store = await fgaClient.GetStore();\n\n// store = { \"id\": \"01FQH7V8BEG3GPQW93KTRFR8JB\", \"name\": \"FGA Demo Store\", \"created_at\": \"2022-01-01T00:00:00.000Z\", \"updated_at\": \"2022-01-01T00:00:00.000Z\" }\n```\n\n##### Delete Store\n\nDelete a store.\n\n[API Documentation](https://openfga.dev/api/service#/Stores/DeleteStore)\n\n\u003e Requires a client initialized with a storeId\n\n```csharp\nvar store = await fgaClient.DeleteStore();\n```\n\n#### Authorization Models\n\n##### Read Authorization Models\n\nRead all authorization models in the store.\n\n[API Documentation](https://openfga.dev/api/service#/Authorization%20Models/ReadAuthorizationModels)\n\n```csharp\nvar options = new ClientReadAuthorizationModelsOptions {\n    PageSize = 10,\n    ContinuationToken = \"...\",\n};\nvar response = await fgaClient.ReadAuthorizationModels(options);\n\n// response.AuthorizationModels = [\n// { Id: \"01GXSA8YR785C4FYS3C0RTG7B1\", SchemaVersion: \"1.1\", TypeDefinitions: [...] },\n// { Id: \"01GXSBM5PVYHCJNRNKXMB4QZTW\", SchemaVersion: \"1.1\", TypeDefinitions: [...] }];\n```\n\n##### Write Authorization Model\n\nCreate a new authorization model.\n\n[API Documentation](https://openfga.dev/api/service#/Authorization%20Models/WriteAuthorizationModel)\n\n\u003e Note: To learn how to build your authorization model, check the Docs at https://openfga.dev/docs.\n\n\u003e Learn more about [the OpenFGA configuration language](https://openfga.dev/docs/configuration-language).\n\n\u003e You can use the [OpenFGA Syntax Transformer](https://github.com/openfga/syntax-transformer) to convert between the friendly DSL and the JSON authorization model.\n\n```csharp\n\nvar body = new ClientWriteAuthorizationModelRequest {\n    SchemaVersion = \"1.1\",\n    TypeDefinitions = new List\u003cTypeDefinition\u003e {\n        new() {Type = \"user\", Relations = new Dictionary\u003cstring, Userset\u003e()},\n        new() {Type = \"document\",\n            Relations = new Dictionary\u003cstring, Userset\u003e {\n                {\"writer\", new Userset {This = new object()}}, {\n                    \"viewer\", new Userset {\n                        Union = new Usersets {\n                            Child = new List\u003cUserset\u003e {\n                                new() {This = new object()},\n                                new() {ComputedUserset = new ObjectRelation {Relation = \"writer\"}}\n                            }\n                        }\n                    }\n                }\n            },\n            Metadata = new Metadata {\n                Relations = new Dictionary\u003cstring, RelationMetadata\u003e {\n                    {\"writer\", new RelationMetadata {\n                        DirectlyRelatedUserTypes = new List\u003cRelationReference\u003e {\n                            new() {Type = \"user\"}\n                        }\n                    }}, {\"viewer\", new RelationMetadata {\n                        DirectlyRelatedUserTypes = new List\u003cRelationReference\u003e {\n                            new() {Type = \"user\"}\n                        }\n                    }}\n                }\n            }\n        }\n    }\n};\n\nvar response = await fgaClient.WriteAuthorizationModel(body);\n\n// response.AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\"\n```\n\n#### Read a Single Authorization Model\n\nRead a particular authorization model.\n\n[API Documentation](https://openfga.dev/api/service#/Authorization%20Models/ReadAuthorizationModel)\n\n```csharp\nvar options = new ClientReadAuthorizationModelOptions {\n    // You can rely on the model id set in the configuration or override it for this specific request\n    AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\",\n};\n\nvar response = await fgaClient.ReadAuthorizationModel(options);\n\n// response.AuthorizationModel.Id = \"01GXSA8YR785C4FYS3C0RTG7B1\"\n// response.AuthorizationModel.SchemaVersion = \"1.1\"\n// response.AuthorizationModel.TypeDefinitions = [{ \"type\": \"document\", \"relations\": { ... } }, { \"type\": \"user\", \"relations\": { ... }}]\n```\n\n##### Read the Latest Authorization Model\n\nReads the latest authorization model (note: this ignores the model id in configuration).\n\n[API Documentation](https://openfga.dev/api/service#/Authorization%20Models/ReadAuthorizationModel)\n\n```csharp\nvar response = await fgaClient.ReadLatestAuthorizationModel();\n\n// response.AuthorizationModel.Id = \"01GXSA8YR785C4FYS3C0RTG7B1\"\n// response.AuthorizationModel.SchemaVersion = \"1.1\"\n// response.AuthorizationModel.TypeDefinitions = [{ \"type\": \"document\", \"relations\": { ... } }, { \"type\": \"user\", \"relations\": { ... }}]\n```\n\n#### Relationship Tuples\n\n##### Read Relationship Tuple Changes (Watch)\n\nReads the list of historical relationship tuple writes and deletes.\n\n[API Documentation](https://openfga.dev/api/service#/Relationship%20Tuples/ReadChanges)\n\n```csharp\nvar body = new ClientReadChangesRequest { Type = \"document\" };\nvar options = new ClientReadChangesOptions {\n    PageSize = 10,\n    ContinuationToken = \"...\",\n};\n\nvar response = await fgaClient.ReadChanges(body, options);\n\n// response.ContinuationToken = ...\n// response.Changes = [\n//   { TupleKey: { User, Relation, Object }, Operation: TupleOperation.WRITE, Timestamp: ... },\n//   { TupleKey: { User, Relation, Object }, Operation: TupleOperation.DELETE, Timestamp: ... }\n// ]\n```\n\n##### Read Relationship Tuples\n\nReads the relationship tuples stored in the database. It does not evaluate nor exclude invalid tuples according to the authorization model.\n\n[API Documentation](https://openfga.dev/api/service#/Relationship%20Tuples/Read)\n\n```csharp\n// Find if a relationship tuple stating that a certain user is a viewer of a certain document\nvar body = new ClientReadRequest() {\n    User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Relation = \"viewer\",\n    Object = \"document:roadmap\",\n};\n\n// Find all relationship tuples where a certain user has a relationship as any relation to a certain document\nvar body = new ClientReadRequest() {\n    User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Object = \"document:roadmap\",\n};\n\n// Find all relationship tuples where a certain user is a viewer of any document\nvar body = new ClientReadRequest() {\n    User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Relation = \"viewer\",\n    Object = \"document:\",\n};\n\n// Find all relationship tuples where any user has a relationship as any relation with a particular document\n\nvar body = new ClientReadRequest() {\n    Object = \"document:roadmap\",\n};\n\n// Read all stored relationship tuples\nvar body = new ClientReadRequest();\n\nvar options = new ClientReadOptions {\n    PageSize = 10,\n    ContinuationToken = \"...\",\n};\n\nvar response = await fgaClient.Read(body, options);\n\n// In all the above situations, the response will be of the form:\n// response = { Tuples: [{ Key: { User, Relation, Object }, Timestamp }, ...]}\n```\n\n##### Write (Create and Delete) Relationship Tuples\n\nCreate and/or delete relationship tuples to update the system state.\n\n[API Documentation](https://openfga.dev/api/service#/Relationship%20Tuples/Write)\n\n###### Transaction mode (default)\n\nBy default, write runs in a transaction mode where any invalid operation (deleting a non-existing tuple, creating an existing tuple, one of the tuples was invalid) or a server error will fail the entire operation.\n\n```csharp\nvar body = new ClientWriteRequest() {\n    Writes = new List\u003cClientTupleKey\u003e {\n        new() {\n            User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n            Relation = \"viewer\",\n            Object = \"document:roadmap\",\n        },\n        new() {\n            User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n            Relation = \"viewer\",\n            Object = \"document:budget\",\n        }\n    },\n    Deletes = new List\u003cClientTupleKeyWithoutCondition\u003e {\n        new() {\n            User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n            Relation = \"writer\",\n            Object = \"document:roadmap\",\n        }\n    },\n};\nvar options = new ClientWriteOptions {\n    // You can rely on the model id set in the configuration or override it for this specific request\n    AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\",\n};\nvar response = await fgaClient.Write(body, options);\n```\n\nConvenience `WriteTuples` and `DeleteTuples` methods are also available.\n\n###### Non-transaction mode\n\nThe SDK will split the writes into separate requests and send them sequentially to avoid violating rate limits.\n\n```csharp\nvar body = new ClientWriteRequest() {\n    Writes = new List\u003cClientTupleKey\u003e {\n        new() {\n            User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n            Relation = \"viewer\",\n            Object = \"document:roadmap\",\n        },\n        new() {\n            User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n            Relation = \"viewer\",\n            Object = \"document:budget\",\n        }\n    },\n    Deletes = new List\u003cClientTupleKeyWithoutCondition\u003e {\n        new() {\n            User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n            Relation = \"writer\",\n            Object = \"document:roadmap\",\n        }\n    },\n};\nvar options = new ClientWriteOptions {\n    // You can rely on the model id set in the configuration or override it for this specific request\n    AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\",\n    Transaction = new TransactionOptions() {\n        Disable = true,\n        MaxParallelRequests = 5, // Maximum number of requests to issue in parallel\n        MaxPerChunk = 1, // Maximum number of requests to be sent in a transaction in a particular chunk\n    }\n};\nvar response = await fgaClient.Write(body, options);\n```\n\n#### Relationship Queries\n\n##### Check\n\nCheck if a user has a particular relation with an object.\n\n[API Documentation](https://openfga.dev/api/service#/Relationship%20Queries/Check)\n\n```csharp\nvar options = new ClientCheckOptions {\n    // You can rely on the model id set in the configuration or override it for this specific request\n    AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\",\n};\nvar body = new ClientCheckRequest {\n    User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Relation = \"writer\",\n    Object = \"document:roadmap\"\n};\nvar response = await fgaClient.Check(body, options);\n// response.Allowed = true\n```\n\n##### Batch Check\n\nRun a set of [checks](#check). Batch Check will return `allowed: false` if it encounters an error, and will return the error in the body.\nIf 429s or 5xxs are encountered, the underlying check will retry up to 15 times before giving up.\n\n```csharp\nvar options = new ClientBatchCheckOptions {\n    // You can rely on the model id set in the configuration or override it for this specific request\n    AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\",\n    MaxParallelRequests = 5, // Max number of requests to issue in parallel, defaults to 10\n};\nvar body = new List\u003cClientCheckRequest\u003e(){\n    new() {\n        User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n        Relation = \"viewer\",\n        Object = \"document:roadmap\",\n        ContextualTuples = new List\u003cClientTupleKey\u003e() {\n            new() {\n                User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n                Relation = \"editor\",\n                Object = \"document:roadmap\",\n            }\n        },\n    },\n    new() {\n        User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n        Relation = \"admin\",\n        Object = \"document:roadmap\",\n        ContextualTuples = new List\u003cClientTupleKey\u003e() {\n            new() {\n                User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n                Relation = \"editor\",\n                Object = \"document:roadmap\",\n            }\n        },\n    },\n    new() {\n        User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n        Relation = \"creator\",\n        Object = \"document:roadmap\",\n    },\n    new() {\n        User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n        Relation = \"deleter\",\n        Object = \"document:roadmap\",\n    }\n};\n\nvar response = await fgaClient.BatchCheck(body, options);\n\n/*\nresponse.Responses = [{\n  Allowed: false,\n  Request: {\n    User: \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Relation: \"viewer\",\n    Object: \"document:roadmap\",\n    ContextualTuples: [{\n      User: \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n      Relation: \"editor\",\n      Object: \"document:roadmap\"\n    }]\n  }\n}, {\n  Allowed: false,\n  Request: {\n    User: \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Relation: \"admin\",\n    Object: \"document:roadmap\",\n    ContextualTuples: [{\n      User: \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n      Relation: \"editor\",\n      Object: \"document:roadmap\"\n    }]\n  }\n}, {\n  Allowed: false,\n  Request: {\n    User: \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Relation: \"creator\",\n    Object: \"document:roadmap\",\n  },\n  Error: \u003cFgaError ...\u003e\n}, {\n  Allowed: true,\n  Request: {\n    User: \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Relation: \"deleter\",\n    Object: \"document:roadmap\",\n  }},\n]\n*/\n```\n\n##### Expand\n\nExpands the relationships in userset tree format.\n\n[API Documentation](https://openfga.dev/api/service#/Relationship%20Queries/Expand)\n\n```csharp\nvar options = new ClientCheckOptions {\n    // You can rely on the model id set in the configuration or override it for this specific request\n    AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\",\n};\nvar body = new ClientExpandRequest {\n    Relation = \"viewer\",\n    Object = \"document:roadmap\",\n};\nvar response = await fgaClient.Expand(body, options);\n\n// response.Tree.Root = {\"name\":\"document:roadmap#viewer\",\"leaf\":{\"users\":{\"users\":[\"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\"user:f52a4f7a-054d-47ff-bb6e-3ac81269988f\"]}}}\n```\n\n##### List Objects\n\nList the objects of a particular type a user has access to.\n\n[API Documentation](https://openfga.dev/api/service#/Relationship%20Queries/ListObjects)\n\n```csharp\nvar options = new ClientListObjectsOptions {\n    // You can rely on the model id set in the configuration or override it for this specific request\n    AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\",\n};\nvar body = new ClientListObjectsRequest {\n    User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Relation = \"viewer\",\n    Type = \"document\",\n    ContextualTuples = new List\u003cClientTupleKey\u003e {\n        new() {\n            User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n            Relation = \"writer\",\n            Object = \"document:budget\",\n        },\n    },\n};\nvar response = await fgaClient.ListObjects(body, options);\n\n// response.Objects = [\"document:roadmap\"]\n```\n\n##### List Relations\n\nList the relations a user has on an object.\n\n```csharp\nListRelationsRequest body =\n    new ListRelationsRequest() {\n        User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n        Object = \"document:roadmap\",\n        Relations = new List\u003cstring\u003e {\"can_view\", \"can_edit\", \"can_delete\", \"can_rename\"},\n        ContextualTuples = new List\u003cClientTupleKey\u003e() {\n            new ClientTupleKey {\n                User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n                Relation = \"editor\",\n                Object = \"document:roadmap\",\n            }\n        }\n    };\nvar response = await fgaClient.ListRelations(body);\n\n// response.Relations = [\"can_view\", \"can_edit\"]\n```\n\n##### List Users\n\nList the users who have a certain relation to a particular type.\n\n[API Documentation](https://openfga.dev/api/service#/Relationship%20Queries/ListUsers)\n\n```csharp\nconst options = {};\n\n// To override the authorization model id for this request\noptions.authorization_model_id = \"1uHxCSuTP0VKPYSnkq1pbb1jeZw\";\n\n// Only a single filter is allowed for the time being\nconst userFilters = [{type: \"user\"}];\n// user filters can also be of the form\n// const userFilters = [{type: \"team\", relation: \"member\"}];\n\nconst response = await fgaClient.listUsers({\n  object: {\n    type: \"document\",\n    id: \"roadmap\"\n  },\n  relation: \"can_read\",\n  user_filters: userFilters,\n  context: {\n    \"view_count\": 100\n  },\n  contextualTuples:\n    [{\n      user: \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n      relation: \"editor\",\n      object: \"folder:product\"\n    }, {\n      user: \"folder:product\",\n      relation: \"parent\",\n      object: \"document:roadmap\"\n    }]\n}, options);\n\n// response.users = [{object: {type: \"user\", id: \"81684243-9356-4421-8fbf-a4f8d36aa31b\"}}, {userset: { type: \"user\" }}, ...]\n```\n\n#### Assertions\n\n##### Read Assertions\n\nRead assertions for a particular authorization model.\n\n[API Documentation](https://openfga.dev/api/service#/Assertions/Read%20Assertions)\n\n```csharp\nvar options = new ClientReadAssertionsOptions {\n    // You can rely on the model id set in the configuration or override it for this specific request\n    AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\",\n};\nvar response = await fgaClient.ReadAssertions(options);\n```\n\n##### Write Assertions\n\nUpdate the assertions for a particular authorization model.\n\n[API Documentation](https://openfga.dev/api/service#/Assertions/Write%20Assertions)\n\n```csharp\nvar options = new ClientWriteAssertionsOptions {\n    // You can rely on the model id set in the configuration or override it for this specific request\n    AuthorizationModelId = \"01GXSA8YR785C4FYS3C0RTG7B1\",\n};\nvar body = new List\u003cClientAssertion\u003e() {new ClientAssertion() {\n    User = \"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\n    Relation = \"viewer\",\n    Object = \"document:roadmap\",\n    Expectation = true,\n}};\nawait fgaClient.WriteAssertions(body, options);\n```\n\n\n### Retries\n\nIf a network request fails with a 429 or 5xx error from the server, the SDK will automatically retry the request up to 15 times with a minimum wait time of 100 milliseconds between each attempt.\n\nTo customize this behavior, create a `RetryParams` instance and assign values to the `MaxRetry` and `MinWaitInMs` constructor parameters. `MaxRetry` determines the maximum number of retries (up to 15), while `MinWaitInMs` sets the minimum wait time between retries in milliseconds.\n\nApply your custom retry values by passing the object to the `ClientConfiguration` constructor's `RetryParams` parameter.\n\n```csharp\nusing OpenFga.Sdk.Client;\nusing OpenFga.Sdk.Client.Model;\nusing OpenFga.Sdk.Model;\n\nnamespace Example {\n    public class Example {\n        public static async Task Main() {\n            try {\n                var configuration = new ClientConfiguration() {\n                    ApiUrl = Environment.GetEnvironmentVariable(\"FGA_API_URL\") ?? \"http://localhost:8080\", // required, e.g. https://api.fga.example\n                    StoreId = Environment.GetEnvironmentVariable(\"FGA_STORE_ID\"), // not needed when calling `CreateStore` or `ListStores`\n                    AuthorizationModelId = Environment.GetEnvironmentVariable(\"FGA_MODEL_ID\"), // Optional, can be overridden per request\n                    RetryParams = new RetryParams() {\n                        MaxRetry = 3, // retry up to 3 times on API requests\n                        MinWaitInMs = 250 // wait a minimum of 250 milliseconds between requests\n                    }\n                };\n                var fgaClient = new OpenFgaClient(configuration);\n                var response = await fgaClient.ReadAuthorizationModels();\n            } catch (ApiException e) {\n                 Debug.Print(\"Error: \"+ e);\n            }\n        }\n    }\n}\n```\n\n### API Endpoints\n\n| Method | HTTP request | Description |\n| ------------- | ------------- | ------------- |\n| [**Check**](docs/OpenFgaApi.md#check) | **POST** /stores/{store_id}/check | Check whether a user is authorized to access an object |\n| [**CreateStore**](docs/OpenFgaApi.md#createstore) | **POST** /stores | Create a store |\n| [**DeleteStore**](docs/OpenFgaApi.md#deletestore) | **DELETE** /stores/{store_id} | Delete a store |\n| [**Expand**](docs/OpenFgaApi.md#expand) | **POST** /stores/{store_id}/expand | Expand all relationships in userset tree format, and following userset rewrite rules.  Useful to reason about and debug a certain relationship |\n| [**GetStore**](docs/OpenFgaApi.md#getstore) | **GET** /stores/{store_id} | Get a store |\n| [**ListObjects**](docs/OpenFgaApi.md#listobjects) | **POST** /stores/{store_id}/list-objects | List all objects of the given type that the user has a relation with |\n| [**ListStores**](docs/OpenFgaApi.md#liststores) | **GET** /stores | List all stores |\n| [**ListUsers**](docs/OpenFgaApi.md#listusers) | **POST** /stores/{store_id}/list-users | List the users matching the provided filter who have a certain relation to a particular type. |\n| [**Read**](docs/OpenFgaApi.md#read) | **POST** /stores/{store_id}/read | Get tuples from the store that matches a query, without following userset rewrite rules |\n| [**ReadAssertions**](docs/OpenFgaApi.md#readassertions) | **GET** /stores/{store_id}/assertions/{authorization_model_id} | Read assertions for an authorization model ID |\n| [**ReadAuthorizationModel**](docs/OpenFgaApi.md#readauthorizationmodel) | **GET** /stores/{store_id}/authorization-models/{id} | Return a particular version of an authorization model |\n| [**ReadAuthorizationModels**](docs/OpenFgaApi.md#readauthorizationmodels) | **GET** /stores/{store_id}/authorization-models | Return all the authorization models for a particular store |\n| [**ReadChanges**](docs/OpenFgaApi.md#readchanges) | **GET** /stores/{store_id}/changes | Return a list of all the tuple changes |\n| [**Write**](docs/OpenFgaApi.md#write) | **POST** /stores/{store_id}/write | Add or delete tuples from the store |\n| [**WriteAssertions**](docs/OpenFgaApi.md#writeassertions) | **PUT** /stores/{store_id}/assertions/{authorization_model_id} | Upsert assertions for an authorization model ID |\n| [**WriteAuthorizationModel**](docs/OpenFgaApi.md#writeauthorizationmodel) | **POST** /stores/{store_id}/authorization-models | Create a new authorization model |\n\n\n\n### Models\n\n - [Model.AbortedMessageResponse](docs/AbortedMessageResponse.md)\n - [Model.Any](docs/Any.md)\n - [Model.Assertion](docs/Assertion.md)\n - [Model.AssertionTupleKey](docs/AssertionTupleKey.md)\n - [Model.AuthorizationModel](docs/AuthorizationModel.md)\n - [Model.CheckRequest](docs/CheckRequest.md)\n - [Model.CheckRequestTupleKey](docs/CheckRequestTupleKey.md)\n - [Model.CheckResponse](docs/CheckResponse.md)\n - [Model.Computed](docs/Computed.md)\n - [Model.Condition](docs/Condition.md)\n - [Model.ConditionMetadata](docs/ConditionMetadata.md)\n - [Model.ConditionParamTypeRef](docs/ConditionParamTypeRef.md)\n - [Model.ConsistencyPreference](docs/ConsistencyPreference.md)\n - [Model.ContextualTupleKeys](docs/ContextualTupleKeys.md)\n - [Model.CreateStoreRequest](docs/CreateStoreRequest.md)\n - [Model.CreateStoreResponse](docs/CreateStoreResponse.md)\n - [Model.Difference](docs/Difference.md)\n - [Model.ErrorCode](docs/ErrorCode.md)\n - [Model.ExpandRequest](docs/ExpandRequest.md)\n - [Model.ExpandRequestTupleKey](docs/ExpandRequestTupleKey.md)\n - [Model.ExpandResponse](docs/ExpandResponse.md)\n - [Model.FgaObject](docs/FgaObject.md)\n - [Model.GetStoreResponse](docs/GetStoreResponse.md)\n - [Model.InternalErrorCode](docs/InternalErrorCode.md)\n - [Model.InternalErrorMessageResponse](docs/InternalErrorMessageResponse.md)\n - [Model.Leaf](docs/Leaf.md)\n - [Model.ListObjectsRequest](docs/ListObjectsRequest.md)\n - [Model.ListObjectsResponse](docs/ListObjectsResponse.md)\n - [Model.ListStoresResponse](docs/ListStoresResponse.md)\n - [Model.ListUsersRequest](docs/ListUsersRequest.md)\n - [Model.ListUsersResponse](docs/ListUsersResponse.md)\n - [Model.Metadata](docs/Metadata.md)\n - [Model.Node](docs/Node.md)\n - [Model.Nodes](docs/Nodes.md)\n - [Model.NotFoundErrorCode](docs/NotFoundErrorCode.md)\n - [Model.NullValue](docs/NullValue.md)\n - [Model.ObjectRelation](docs/ObjectRelation.md)\n - [Model.PathUnknownErrorMessageResponse](docs/PathUnknownErrorMessageResponse.md)\n - [Model.ReadAssertionsResponse](docs/ReadAssertionsResponse.md)\n - [Model.ReadAuthorizationModelResponse](docs/ReadAuthorizationModelResponse.md)\n - [Model.ReadAuthorizationModelsResponse](docs/ReadAuthorizationModelsResponse.md)\n - [Model.ReadChangesResponse](docs/ReadChangesResponse.md)\n - [Model.ReadRequest](docs/ReadRequest.md)\n - [Model.ReadRequestTupleKey](docs/ReadRequestTupleKey.md)\n - [Model.ReadResponse](docs/ReadResponse.md)\n - [Model.RelationMetadata](docs/RelationMetadata.md)\n - [Model.RelationReference](docs/RelationReference.md)\n - [Model.RelationshipCondition](docs/RelationshipCondition.md)\n - [Model.SourceInfo](docs/SourceInfo.md)\n - [Model.Status](docs/Status.md)\n - [Model.Store](docs/Store.md)\n - [Model.Tuple](docs/Tuple.md)\n - [Model.TupleChange](docs/TupleChange.md)\n - [Model.TupleKey](docs/TupleKey.md)\n - [Model.TupleKeyWithoutCondition](docs/TupleKeyWithoutCondition.md)\n - [Model.TupleOperation](docs/TupleOperation.md)\n - [Model.TupleToUserset](docs/TupleToUserset.md)\n - [Model.TypeDefinition](docs/TypeDefinition.md)\n - [Model.TypeName](docs/TypeName.md)\n - [Model.TypedWildcard](docs/TypedWildcard.md)\n - [Model.UnauthenticatedResponse](docs/UnauthenticatedResponse.md)\n - [Model.UnprocessableContentErrorCode](docs/UnprocessableContentErrorCode.md)\n - [Model.UnprocessableContentMessageResponse](docs/UnprocessableContentMessageResponse.md)\n - [Model.User](docs/User.md)\n - [Model.UserTypeFilter](docs/UserTypeFilter.md)\n - [Model.Users](docs/Users.md)\n - [Model.Userset](docs/Userset.md)\n - [Model.UsersetTree](docs/UsersetTree.md)\n - [Model.UsersetTreeDifference](docs/UsersetTreeDifference.md)\n - [Model.UsersetTreeTupleToUserset](docs/UsersetTreeTupleToUserset.md)\n - [Model.UsersetUser](docs/UsersetUser.md)\n - [Model.Usersets](docs/Usersets.md)\n - [Model.ValidationErrorMessageResponse](docs/ValidationErrorMessageResponse.md)\n - [Model.WriteAssertionsRequest](docs/WriteAssertionsRequest.md)\n - [Model.WriteAuthorizationModelRequest](docs/WriteAuthorizationModelRequest.md)\n - [Model.WriteAuthorizationModelResponse](docs/WriteAuthorizationModelResponse.md)\n - [Model.WriteRequest](docs/WriteRequest.md)\n - [Model.WriteRequestDeletes](docs/WriteRequestDeletes.md)\n - [Model.WriteRequestWrites](docs/WriteRequestWrites.md)\n\n\n\n### OpenTelemetry\n\nThis SDK supports producing metrics that can be consumed as part of an [OpenTelemetry](https://opentelemetry.io/) setup. For more information, please see [the documentation](https://github.com/openfga/dotnet-sdk/blob/main/OpenTelemetry.md)\n\n## Contributing\n\n### Issues\n\nIf you have found a bug or if you have a feature request, please report them on the [sdk-generator repo](https://github.com/openfga/sdk-generator/issues) issues section. Please do not report security vulnerabilities on the public GitHub issue tracker.\n\n### Pull Requests\n\nAll changes made to this repo will be overwritten on the next generation, so we kindly ask that you send all pull requests related to the SDKs to the [sdk-generator repo](https://github.com/openfga/sdk-generator) instead.\n\n## Author\n\n[OpenFGA](https://github.com/openfga)\n\n## License\n\nThis project is licensed under the Apache-2.0 license. See the [LICENSE](https://github.com/openfga/dotnet-sdk/blob/main/LICENSE) file for more info.\n\nThe code in this repo was auto generated by [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator) from a template based on the [csharp-netcore template](https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/resources/csharp-netcore), licensed under the [Apache License 2.0](https://github.com/OpenAPITools/openapi-generator/blob/master/LICENSE).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenfga%2Fdotnet-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenfga%2Fdotnet-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenfga%2Fdotnet-sdk/lists"}