Install & Compatibility
Where this runs
tested against v0.10.4 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.894s · 32.2MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 4.4s · import 0.786s · 34MB
32MB installed
● package 32MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
OpenFgaClient
✓ from openfga_sdk import OpenFgaClient
✗ from openfga_sdk.client import OpenFgaClient
The primary client class was moved from `openfga_sdk.client` to the top-level `openfga_sdk` package in version 0.8.0 for simpler imports.
Credentials
✓ from openfga_sdk import Credentials
Authentication credentials are provided via the Credentials class, imported directly from the top-level package.
Models
✓ from openfga_sdk.models import WriteRequest, TupleKey, User, Relation, Object, CheckRequest
✗ from openfga_sdk.client import Models
API model classes (e.g., `WriteRequest`, `User`, `Object`) were moved from `openfga_sdk.client` to `openfga_sdk.models` in version 0.7.0. They should be imported individually or as needed from the `models` submodule.
Initialize the OpenFGA client, write an authorization model tuple, and perform a check. This example demonstrates basic 'Write' and 'Check' operations. Ensure `FGA_API_URL` and `FGA_STORE_ID` (and authentication variables like `FGA_API_TOKEN`) are set in your environment. The provided `fga_store_id` is an example and must be replaced with a real one from your OpenFGA setup.
import os
from openfga_sdk import OpenFgaClient, Credentials
from openfga_sdk.models import WriteRequest, TupleKey, User, Relation, Object, CheckRequest
# Configure OpenFGA client using environment variables for sensitive data.
# Required: FGA_API_URL, FGA_STORE_ID
# Optional (for auth): FGA_API_TOKEN or FGA_CLIENT_ID/FGA_CLIENT_SECRET/FGA_TOKEN_URL/FGA_AUDIENCE
fga_api_url = os.environ.get("FGA_API_URL", "http://localhost:8080")
fga_store_id = os.environ.get("FGA_STORE_ID", "01H4F8G5K4S8K7J2G8R1T0V9M0") # Replace with your actual Store ID
credentials = None
api_token = os.environ.get("FGA_API_TOKEN")
if api_token:
credentials = Credentials(api_token=api_token)
elif os.environ.get("FGA_CLIENT_ID") and os.environ.get("FGA_CLIENT_SECRET"):
# Example for Client Credentials flow with OAuth2 (replace with your IdP details)
credentials = Credentials(
client_id=os.environ.get("FGA_CLIENT_ID", ""),
client_secret=os.environ.get("FGA_CLIENT_SECRET", ""),
token_url=os.environ.get("FGA_TOKEN_URL", "https://auth.fga.example.com/oauth/token"),
audience=os.environ.get("FGA_AUDIENCE", fga_api_url) # Audience often matches API URL
)
if not fga_store_id:
raise ValueError("FGA_STORE_ID environment variable is required.")
client = OpenFgaClient(
api_url=fga_api_url,
store_id=fga_store_id,
credentials=credentials,
)
try:
# 1. Write a relationship: "user:anne can view document:roadmap"
write_response = client.write(
body=WriteRequest(
writes=[
TupleKey(
user=User(id="anne"),
relation="viewer",
object=Object(type="document", id="roadmap")
)
]
)
)
print(f"Wrote relationship: user:anne is viewer of document:roadmap")
# 2. Check if "user:anne can view document:roadmap"
check_response = client.check(
body=CheckRequest(
user=User(id="anne"),
relation="viewer",
object=Object(type="document", id="roadmap")
)
)
print(f"Check result (anne can view roadmap): {check_response.allowed}") # Expected: True
# 3. Check if "user:bob can view document:roadmap" (assuming bob has no relation)
check_response_bob = client.check(
body=CheckRequest(
user=User(id="bob"),
relation="viewer",
object=Object(type="document", id="roadmap")
)
)
print(f"Check result (bob can view roadmap): {check_response_bob.allowed}") # Expected: False
except Exception as e:
print(f"An error occurred: {e}")
# The client uses an httpx.Client which is typically managed internally.
# No explicit close() is necessary for OpenFgaClient as of v0.10.0 in most cases.
Errors
Common errors & fixes
openfga_sdk.exceptions.ApiException: [HTTP 400] type 'invalid_type' not found (validation_error)
The SDK received an error response from the OpenFGA API server, indicating issues like an invalid type in the authorization model, incorrect request parameters, or other validation failures.
fixImplement `try...except ApiException as e:` to catch and inspect the error. Use `e.error_message`, `e.error_code`, `e.is_validation_error()` to understand the specific API error. Ensure your authorization model is correctly defined and the data being sent adheres to it.
ApiException: [write] HTTP 400 type 'cannot_allow_duplicate_tuples_in_one_request' (validation_error)
You attempted to write a relationship tuple that already exists within the OpenFGA store in a single request, and the default SDK behavior is to fail the entire write operation.
fixWhen calling the `write` method, pass `conflict=ClientWriteOptions(on_duplicate='ignore')` in the request body to instruct OpenFGA to skip existing tuples instead of failing the request.
ValueError: ClientConfiguration requires 'api_url' to be set.
The `OpenFgaClient` was initialized without providing the required `api_url` in its `ClientConfiguration`, which is essential for the SDK to connect to your OpenFGA server.
fixEnsure that `api_url` is explicitly set in the `ClientConfiguration` when initializing `OpenFgaClient`, typically loaded from an environment variable. Example: `ClientConfiguration(api_url=os.environ.get('FGA_API_URL'), ...)` ApiException: [check] HTTP 400 missing store_id in request
An API call (like `check`, `write`, `read`) was made without providing a `store_id`, which is required for most operations to specify which OpenFGA store to interact with.
fixSet the `store_id` in your `ClientConfiguration` when initializing `OpenFgaClient`, or provide it in the options for the specific API call. Example: `ClientConfiguration(store_id=os.environ.get('FGA_STORE_ID'), ...)` AttributeError: 'ClientResponse' object has no attribute 'data'
This is an internal bug in older versions of the `openfga-sdk` where the exception handling code incorrectly attempted to access a non-existent `data` attribute on an `aiohttp.ClientResponse` object, preventing the correct OpenFGA API error from being propagated.
fixUpgrade the `openfga-sdk` to its latest version (`pip install --upgrade openfga-sdk`) as this specific bug related to error reporting was identified and addressed in subsequent releases.
Upgrade
Version history
0.10.4latest on PyPI · released Jun 29, 2026
Audit
Dependencies
httpxrequiredUsed as the underlying asynchronous HTTP client for API communication.
pydanticrequiredUsed for data validation and serialization/deserialization of API models.