{"id":4887,"library":"authzed","title":"Authzed Python Client","description":"The `authzed` library is the official Python client for Authzed's SpiceDB, a permissions database and service. It enables developers to define authorization schemas, manage relationships between objects, and perform efficient permission checks within their applications. The library supports both the v1 Core SpiceDB API and the materialize/v0 API for building materialized permission views. It maintains an active development status with regular updates.","status":"active","version":"1.24.4","language":"en","source_language":"en","source_url":"https://github.com/authzed/authzed-py","tags":["authorization","permissions","rbac","abac","grpc","spicedb"],"install":[{"cmd":"pip install authzed","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Core dependency for gRPC communication with SpiceDB.","package":"grpcio"},{"reason":"Required for Protocol Buffers serialization/deserialization used by gRPC.","package":"protobuf"},{"reason":"Optional dependency for schema validation tooling.","package":"protovalidate","optional":true}],"imports":[{"symbol":"Client","correct":"from authzed.api.v1 import Client"},{"note":"`grpcutil` is typically imported directly, not as a submodule of `authzed`.","wrong":"from authzed.grpcutil import bearer_token_credentials","symbol":"bearer_token_credentials","correct":"from grpcutil import bearer_token_credentials"},{"note":"Used for local development without TLS/self-signed certificates.","symbol":"insecure_bearer_token_credentials","correct":"from grpcutil import insecure_bearer_token_credentials"}],"quickstart":{"code":"import os\nfrom authzed.api.v1 import Client, CheckPermissionRequest, ObjectReference, SubjectReference\nfrom grpcutil import bearer_token_credentials\n\n# Replace with your SpiceDB endpoint and API token from environment variables\nSPICEDB_ENDPOINT = os.environ.get('SPICEDB_ENDPOINT', 'grpc.authzed.com:443')\nSPICEDB_API_TOKEN = os.environ.get('SPICEDB_API_TOKEN', 't_your_token_here_1234567deadbeef')\n\nif not SPICEDB_API_TOKEN:\n    raise ValueError(\"SPICEDB_API_TOKEN environment variable not set or is empty.\")\n\n# Initialize the client with bearer token credentials\nclient = Client(\n    SPICEDB_ENDPOINT,\n    bearer_token_credentials(SPICEDB_API_TOKEN),\n)\n\ntry:\n    # Example: Check if a user 'emilia' can 'view' a document 'first_doc'\n    request = CheckPermissionRequest(\n        resource=ObjectReference(object_type=\"document\", object_id=\"first_doc\"),\n        permission=\"view\",\n        subject=SubjectReference(object=ObjectReference(object_type=\"user\", object_id=\"emilia\"))\n    )\n    \n    response = client.CheckPermission(request)\n    print(f\"Permission check result: {response.permissionship}\")\n\nexcept Exception as e:\n    print(f\"An error occurred: {e}\")","lang":"python","description":"This quickstart demonstrates how to initialize the Authzed client using an API token and perform a basic permission check. Ensure `SPICEDB_ENDPOINT` and `SPICEDB_API_TOKEN` environment variables are set or replaced with your actual SpiceDB connection details."},"warnings":[{"fix":"For local insecure connections: `from grpcutil import insecure_bearer_token_credentials; client = Client('localhost:50051', insecure_bearer_token_credentials('your_token'))`. For self-signed certs: pass the root certificate as `certChain` to `bearer_token_credentials`.","message":"When developing locally or with self-signed certificates, standard `bearer_token_credentials` might fail due to TLS verification issues. Use `insecure_bearer_token_credentials()` for non-TLS connections or explicitly provide `certChain` for custom certificates.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Implement patterns like the transactional outbox to ensure eventual consistency between your application database and SpiceDB. Avoid treating API calls as RPCs that immediately reflect system state.","message":"The 'Dual-Write Problem' is a common architectural challenge when integrating Authzed/SpiceDB with an application database. Ensuring consistency between both systems (e.g., when creating a file and its permissions) requires careful handling.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For asynchronous use, consider implementing an async-compatible client or using documented workarounds/patterns for async gRPC interactions. Consult the Authzed community for the latest best practices on async usage.","message":"The `InsecureClient` provided by `authzed-py` uses `grpc.insecure_channel`, which is not inherently compatible with `asyncio`. Attempting to use it with asynchronous operations, especially methods like `LookupResources` that return `UnaryStreamCall`, may lead to authentication errors or unexpected behavior.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If encountering unexpected import errors or installation failures after an update, check the project's GitHub issues for known packaging problems. Pinning to a previous stable version may be necessary until a fix is released (e.g., `pip install authzed==1.21.0`).","message":"Periodically, specific minor releases may encounter packaging issues that prevent correct installation or module imports, as was observed with `authzed-py v1.22.0`.","severity":"gotcha","affected_versions":"~1.22.0"},{"fix":"Design schemas carefully to ensure acyclic relationships where possible. If recursion is necessary (e.g., groups having subgroups), ensure the structure directly refers back to itself in a controlled manner, avoiding indirect cycles through other definitions.","message":"Avoid creating cycles in your SpiceDB schema definitions. While recursive schemas can be powerful, incorrect usage or accidental cycles can lead to significant performance issues and unexpected behavior in permission evaluations.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Structure your schema so that a permission points to a relation, and then check the permission. Example: `permission read = reader`, then check `document:id#read@user:id` instead of `document:id#reader@user:id` directly.","message":"When making permission checks, prefer checking permissions directly rather than relations. If the logic for a check needs to change, modifying a permission definition is significantly easier and safer than changing a relation definition, which often requires a data migration.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-12T00:00:00.000Z","next_check":"2026-07-11T00:00:00.000Z"}