Skip to main content
POST /v1/tenants/{tenant_id}/schemas/write The Write Schema endpoint accepts a Permify schema string and stores it as a new versioned schema for the tenant. Each successful write produces a unique schema_version that can be referenced in subsequent read, check, and data-write requests.
The schema must be sent as a single string — newlines should be represented as \n. Use the Permify Playground to model and copy your schema as a formatted string. A VS Code extension with syntax highlighting is also available (file extension .perm).

Path Parameters

tenant_id
string
required
The tenant identifier. Use t1 for single-tenant deployments. Must match ^([a-zA-Z0-9_\-@\.:+]{1,128}|\*)$.

Request Body

schema
string
required
The full authorization schema written in Permify DSL. Entities, relations, attributes, and actions are all defined here.

Response

schema_version
string
The version identifier for the newly written schema. Use this value in metadata.schema_version on subsequent requests to pin them to this schema version.

Example

curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/schemas/write' \
--header 'Content-Type: application/json' \
--data-raw '{
    "schema": "entity user {}\n\nentity organization {\n\n    relation admin @user\n    relation member @user\n\n    action create_repository = (admin or member)\n    action delete = admin\n}\n\nentity repository {\n\n    relation owner @user\n    relation parent @organization\n\n    action push = owner\n    action read = (owner and (parent.admin and parent.member))\n    action delete = (parent.member and (parent.admin or owner))\n}"
}'
Request body
{
  "schema": "entity user {}\n\nentity organization {\n\n    relation admin @user\n    relation member @user\n\n    action create_repository = (admin or member)\n    action delete = admin\n}\n\nentity repository {\n\n    relation owner @user\n    relation parent @organization\n\n    action push = owner\n    action read = (owner and (parent.admin and parent.member))\n    action delete = (parent.member and (parent.admin or owner))\n}"
}
Response
{
  "schema_version": "cnbe6se5fmal18gpc66g"
}

Error Codes

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

Build docs developers (and LLMs) love