Authorization - Authaz - Docs
Authaz Docs Authorization 2 min read· Updated May 7, 2026
Decide who can do what. Set the rules in the dashboard, ask the engine at runtime.
curl -X POST https://your-app.authaz.io/api/v1/authorization/check \
-H "X-API-Key: $AUTHAZ_API_KEY " \
-H "Content-Type: application/json" \
-d '{
"userId": "user_01h...",
"resource": "invoices",
"action": "create",
"tenantId": "tenant_acme"
}'
{ "allowed" : true }
Sub-millisecond. That's the whole runtime API. The rest of this section is what you set up beforehand.
Two ways to grant#
Roles → Policies → Permissions
Roles attach reusable policies. Policies bundle resource:action permissions. Use for "Admins can update invoices."
Direct grants (ReBAC) Grant a single user a relation on a single resource instance. Use for "Alice can read this document."
Both work at the same time. The engine returns one yes/no answer with a full trace.
1. Resources → Catalog every protectable thing in your app and its valid actions. Permissions live here. 2. Policies → Bundle related permissions. invoices_writer = create, read, update, send. 3. Roles → Compose policies into roles. Global or tenant-scoped. 4. Access Explorer → "Can X do Y on Z?" — verdict + reasoning trace. Use when checks don't behave.
You can't reorder this — policies need permissions in the catalog, roles need policies. Build it bottom-up.
Resources
invoices create, read, update, delete, send
customers create, read, update, delete
reports read, export
billing read, update_plan
Policies
invoices_writer invoices:{create,read,update,send}
invoices_reader invoices:read
customer_admin customers:*
reports_viewer reports:read, reports:export
billing_owner billing:{read,update_plan}
Roles
Owner billing_owner + customer_admin + invoices_writer + reports_viewer
Admin customer_admin + invoices_writer + reports_viewer
Member invoices_writer + reports_viewer
Viewer invoices_reader + reports_viewer
Accountant invoices_reader + reports_viewer
Sharing policies across roles means refactoring is editing one place, not three.
Roles are global by default. Pass a tenantId when creating one to scope it — same role name can exist independently in every tenant.
A user can be Owner in tenant A and Viewer in tenant B with the same identity. Permission checks pass tenantId and the engine considers both their global roles and the tenant-scoped ones.
For per-instance access (sharing a document, granting access to one project):
curl -X POST https://your-app.authaz.io/api/v1/authorization/relationships \
-H "X-API-Key: $AUTHAZ_API_KEY " \
-H "Content-Type: application/json" \
-d '{
"userId": "user_01h...",
"resource": "documents",
"resourceId": "doc_01h...",
"relation": "viewer"
}' The user can now do anything viewer allows — but only on that one document. No role required.
When a page renders N rows and gates each one, don't loop:
curl -X POST https://your-app.authaz.io/api/v1/authorization/bulk-check \
-H "X-API-Key: $AUTHAZ_API_KEY " \
-H "Content-Type: application/json" \
-d '{
"userId": "user_01h...",
"checks": [
{ "resource": "invoices", "action": "update", "resourceId": "inv_01" },
{ "resource": "invoices", "action": "delete", "resourceId": "inv_01" },
{ "resource": "invoices", "action": "update", "resourceId": "inv_02" }
]
}' One round-trip, all answers, same sub-millisecond budget per check.
check (single permission)<1 ms typical, single-digit ms p99 bulk-check (N permissions)<1 ms per check, one network round-trip explain (verdict + full trace)5–20 ms — slower; use for Access Explorer , not hot paths
The read path is the optimized path. Use checks freely.