Authorize Access
Check whether a subject is allowed to perform an action on a resource.
POST /access/v1/evaluation
This is the primary endpoint callers use to make authorization decisions. It is natively compliant with the AuthZEN 1.0 authorization API specification.
Request
Headers
| Header | Value |
|---|---|
Authorization | Bearer azx_... |
Content-Type | application/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"
}
},
"resource": {
"type": "document",
"id": "doc-456",
"properties": {
"classification": "internal"
}
},
"action": {
"name": "read"
},
"context": {
"ip": "192.168.1.1"
}
}
Fields
| Field | Type | Required | Description |
|---|---|---|---|
subject.id | string | Yes | Unique identifier of the subject |
subject.type | string | Yes | Type of subject (e.g., user, service) |
subject.external_id | string | No | External identifier from your identity provider — use instead of subject.id when your subjects are identified by your own IDs |
subject.properties | object | No | Key-value attributes for ABAC conditions. Both properties and attributes are accepted and merged; properties takes precedence on key conflicts |
resource.id | string | Conditional | UUID of the resource. Required unless using type + name or external_id lookup |
resource.type | string | Yes | Resource type name. When combined with resource.name, looks up the resource by name instead of UUID |
resource.name | string | Conditional | Resource name. Use with resource.type for name-based lookup |
resource.external_id | string | No | External identifier from your system of record — use instead of resource.id when your resources are identified by your own IDs |
resource.properties | object | No | Key-value attributes for ABAC conditions. Both properties and attributes are accepted and merged; properties takes precedence on key conflicts |
action | object | Yes | The action being requested. Must contain a name field (e.g., {"name": "read"}) |
action.name | string | Yes | Action name (e.g., read, write, delete) |
context | object | No | Additional request-time context for ABAC conditions and guardrails (IP, time, MFA status, etc.). See Context & Trust Model |
Minimal request
At minimum, you need a subject identifier, subject.type, a resource identifier with resource.type, and action. There are three ways to identify the resource — pick whichever matches how your system tracks resources:
By your own ID (external_id — most common):
{
"subject": { "external_id": "alice-uuid-from-your-db", "type": "user" },
"resource": { "external_id": "doc-uuid-from-your-db", "type": "document" },
"action": { "name": "read" }
}
By name:
{
"subject": { "external_id": "alice-uuid-from-your-db", "type": "user" },
"resource": { "type": "document", "name": "Engineering Wiki" },
"action": { "name": "read" }
}
By Vengtoo ID:
{
"subject": { "id": "vengtoo-subject-id", "type": "user" },
"resource": { "id": "vengtoo-resource-id", "type": "document" },
"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",
"reason_code": "NO_POLICY_MATCH",
"access_path": "none"
}
}
Fields
| Field | Type | Description |
|---|---|---|
decision | boolean | Whether access is granted |
context | object | Additional details about the decision |
context.reason | string | Human-readable explanation |
context.reason_code | string | Machine-readable outcome: ALLOWED, NO_POLICY_MATCH, DENY_OVERRIDE, EXPLICIT_DENY, CONDITION_FAILED, ACTION_NOT_PERMITTED |
context.policy_id | string | ID of the matching policy (if allowed) |
context.access_path | string | How access was resolved: "direct", "role", "group", or "none" (deny) |
Error responses
All error responses follow this format:
{ "error": "Description of what went wrong" }
| Status | Description |
|---|---|
400 | Invalid request body — malformed JSON or missing required fields |
401 | Missing or invalid credential |
403 | Valid OAuth2 token but insufficient scope |
500 | Internal authorization error |
If Vengtoo is unreachable or returns a 500, default to deny in your enforcement logic — fail closed, not open.
Example
curl -X POST https://api.vengtoo.com/access/v1/evaluation \
-H "Authorization: Bearer azx_..." \
-H "Content-Type: application/json" \
-H "X-Request-ID: req-abc-123" \
-d '{
"subject": { "external_id": "alice-uuid-from-your-db", "type": "user" },
"resource": { "external_id": "doc-uuid-from-your-db", "type": "document" },
"action": { "name": "read" }
}'