Skip to main content
POST /v1/tenants/{tenant_id}/permissions/check The Check API answers resource-based authorization questions of the form: “Can user U perform action Y on resource Z?” Permify evaluates the check by walking the relationship graph defined in your schema. It runs concurrent queries for each branch of the permission expression (or / and) and short-circuits as soon as a definitive result is found.

Path Parameters

tenant_id
string
required
The tenant identifier. Use the pre-inserted default tenant t1 if you are not using multi-tenancy. Must match ^([a-zA-Z0-9_\-@\.:+]{1,128}|\*)$.

Request Body

metadata
object
required
Controls schema version and caching behavior for this request.
entity
object
required
The resource on which the permission is being checked.
permission
string
required
The permission or relation name to check (e.g. edit, view, push). Must match ^[a-zA-Z_]{1,64}$.
subject
object
required
The subject (user or user set) whose access is being evaluated.
context
object
Contextual data injected dynamically at check time — useful for attribute-based (ABAC) checks without writing tuples.

Response

can
string
The authorization decision. One of:
  • RESULT_ALLOWED — the subject is authorized
  • RESULT_DENIED — the subject is not authorized
metadata
object

Examples

Relationship-based check

curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/permissions/check' \
--header 'Content-Type: application/json' \
--data-raw '{
  "metadata": {
    "snap_token": "",
    "schema_version": "",
    "depth": 20
  },
  "entity": {
    "type": "repository",
    "id": "1"
  },
  "permission": "edit",
  "subject": {
    "type": "user",
    "id": "1",
    "relation": ""
  }
}'
Request body
{
  "metadata": {
    "snap_token": "",
    "schema_version": "",
    "depth": 20
  },
  "entity": {
    "type": "repository",
    "id": "1"
  },
  "permission": "edit",
  "subject": {
    "type": "user",
    "id": "1",
    "relation": ""
  }
}
Response
{
  "can": "RESULT_ALLOWED",
  "metadata": {
    "check_count": 3
  }
}

Attribute-based check with context data

{
  "metadata": {
    "snap_token": "",
    "schema_version": "",
    "depth": 20
  },
  "entity": {
    "type": "organization",
    "id": "1"
  },
  "permission": "hr_manager",
  "subject": {
    "type": "user",
    "id": "1"
  },
  "context": {
    "data": {
      "ip_address": "192.158.1.38"
    }
  }
}

Error Codes

HTTP StatusDescription
400Bad request — missing or invalid fields
401Unauthorized — invalid or missing bearer token
404Tenant not found
429Rate limit exceeded
500Internal server error

Build docs developers (and LLMs) love