Skip to main content

Authorize Access

Check whether a subject is allowed to perform an action on a resource.

POST /v1/authorize

This is the primary endpoint your application calls to make authorization decisions. It is natively compliant with the AuthZEN 1.0 authorization API specification.

Request

Headers

HeaderValue
AuthorizationBearer azx_...
Content-Typeapplication/json
X-Request-ID(optional) A client-generated request ID. If provided, it is echoed back in the response X-Request-ID header for tracing.

Body

{
"subject": {
"id": "user-123",
"type": "user",
"properties": {
"department": "engineering"
},
"roles": ["editor"]
},
"resource": {
"type": "document",
"id": "doc-456",
"properties": {
"classification": "internal"
}
},
"action": {
"name": "read"
},
"context": {
"ip_address": "192.168.1.1"
}
}

Fields

FieldTypeRequiredDescription
subject.idstringYesUnique identifier of the subject
subject.typestringYesType of subject (e.g., user, service)
subject.propertiesobjectNoKey-value properties for ABAC conditions. attributes is accepted as an alias
subject.rolesstring[]NoRoles assigned to the subject
resource.idstringConditionalUUID of the resource. Required unless using type + name lookup
resource.typestringYesResource type name. When combined with resource.name, looks up the resource by name instead of UUID
resource.namestringConditionalResource name. Use with resource.type for name-based lookup
resource.propertiesobjectNoKey-value properties for ABAC conditions. attributes is accepted as an alias
actionobjectYesThe action being requested. Must contain a name field (e.g., {"name": "read"})
action.namestringYesAction name (e.g., read, write, delete)
contextobjectNoAdditional request-time context for ABAC conditions and policy modifiers (IP, time, MFA status, etc.). See Context & Trust Model

:::info Minimal request At minimum, you need subject.id, subject.type, a resource identifier with resource.type, and action. You can identify the resource by UUID or by type + name:

// By UUID
{
"subject": { "id": "user-123", "type": "user" },
"resource": { "id": "doc-456", "type": "document" },
"action": { "name": "read" }
}

// By type + name (recommended — avoids hardcoding UUIDs)
{
"subject": { "id": "user-123", "type": "user" },
"resource": { "type": "document", "name": "Engineering Wiki" },
"action": { "name": "read" }
}

:::

Response

Access allowed

{
"decision": true,
"context": {
"reason": "Access granted via role for entity user-123",
"policy_id": "550e8400-e29b-41d4-a716-446655440000",
"access_path": "role"
}
}

Access denied

{
"decision": false,
"context": {
"reason": "No matching policy found",
"access_path": "none"
}
}

Fields

FieldTypeDescription
decisionbooleanWhether access is granted
contextobjectAdditional details about the decision
context.reasonstringHuman-readable explanation
context.policy_idstringID of the matching policy (if allowed)
context.access_pathstringHow access was granted: "direct", "role", "group", or "none"

Error responses

StatusDescription
400Invalid request body
401Missing or invalid API key
500Internal authorization error

Example

curl -X POST https://api.authzx.com/v1/authorize \
-H "Authorization: Bearer azx_..." \
-H "Content-Type: application/json" \
-H "X-Request-ID: req-abc-123" \
-d '{
"subject": { "id": "user-123", "type": "user" },
"resource": { "id": "doc-456", "type": "document" },
"action": { "name": "read" }
}'

Using SDKs

Instead of raw HTTP calls, use an official SDK:

// Go
decision, _ := client.Check(ctx, authzx.Subject{ID: "user-123", Type: "user"}, authzx.Action{Name: "read"}, authzx.Resource{ID: "doc-456", Type: "document"})
// Node.js
const decision = await authzx.check({ id: 'user-123', type: 'user' }, { name: 'read' }, { id: 'doc-456', type: 'document' })
# Python
decision = client.check(Subject(id="user-123", type="user"), Action(name="read"), Resource(id="doc-456", type="document"))

See SDKs & CLI for installation and full documentation.