> ## Documentation Index
> Fetch the complete documentation index at: https://proxy-docs.permify.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Partial Schema Update

As development teams regularly roll out new features or API endpoints, features each addition often necessitates corresponding updates to the Permify schema.

To streamline this process, we have published an endpoint allows authorized users to make partial updates to the schema by adding or modifying actions within individual entities.

## **Endpoint Definition**

**`/v1/tenants/{tenant_id}/schemas/partial-write`**

This endpoint allows authorized users to make partial updates to the schema by adding or modifying actions within individual entities.

**Request Payload Structure**

```bash theme={null}
PATCH /v1/tenants/{tenant_id}/schemas/partial-write
Content-Type: application/json
```

body:

```json theme={null}
{
  "metadata": {
    "schema_version": ""
  },
  "partials": {
		"<entity-name>": {
			"write": [],
			"delete": [],
			"update": []
		}
  }
}
```

### **Behavior Description**

When the **`schema_version`** in the request metadata is left empty, the system will default to using the latest(head) schema version as the base for updates.

* **`name`** (string): The name of the entity to be changed.
* **`write`** (string array): Conditions to be added. If a relation or permission/action already exists, it should return an error.
* **`delete`** (string array): Names (permissions/actions) to be deleted. If the relation/permission/action name does not exist, it should return an error. Note: specifying the name is enough as relation/permission/action names should be unique.
* **`update`** (string array): Conditions to be updated.

If **`schema_version`** is specified, the endpoint will perform the same update process on the given version and generate a new version thereafter.

**Partial Schema Endpoint Example Usage**

**Existing Schema**

```bash theme={null}
entity user {}

entity organization {
    relation admin @user
    relation member @user
}

entity team {
    relation owner @user
    relation org @organization

    permission edit = org.admin or owner
    permission delete = org.admin or owner
}
```

The code block above outlines the existing schema definitions for the **`user`**, **`organization`**, and **`team`** entities. This includes their respective relationships and permissions within the schema.

### Partial Schema Update Request

To update the **`team`** entity by introducing new permissions, the following PATCH request with the accompanying payload is sent:

```json theme={null}
{
  "metadata": {
    "schema_version": ""
  },
  "partials": {
		"team": {
		  "write": [
		    "relation member @user",
		    "permission invite = org.admin and (owner or member)",
		    "permission remove_user = owner"
		  ],
		  "delete": [
		    "edit"
		  ],
		  "update": [
		    "permission delete = member"
		  ]
		}
	}
}
```

By leaving the **`schema_version`** empty string, it signals the system to take the latest(head) schema version as a base for applying updates.

### **Resulting Schema After Update**

After the request is processed, the system outputs a new schema version where the **`team`** entity is revised to include the new permissions as illustrated below:

```json theme={null}
entity user {}

entity organization {
    relation admin @user
    relation member @user
}

entity team {
    relation owner @user
    relation member @user
    relation org @organization

    permission delete = member
    permission invite = org.admin and (owner or member)
    permission remove_user = owner
}
```

**`invite`** and **`remove_user`** permissions have been added, a **`member`** relation has been included, the **`edit`** permission has been deleted, and the **`delete`** permission has been updated.


## OpenAPI

````yaml patch /v1/tenants/{tenant_id}/schemas/partial-write
openapi: 3.0.0
info:
  title: Permify API
  description: >-
    Permify is an open source authorization service for creating fine-grained
    and scalable authorization systems.
  version: v1.6.10
  contact:
    name: API Support
    url: https://github.com/Permify/permify/issues
    email: hello@permify.co
  license:
    name: AGPL-3.0 license
    url: https://github.com/Permify/permify/blob/master/LICENSE
servers: []
security: []
tags:
  - name: Permission
  - name: Watch
  - name: Schema
  - name: Data
  - name: Bundle
  - name: Tenancy
paths:
  /v1/tenants/{tenant_id}/schemas/partial-write:
    patch:
      tags:
        - Schema
      summary: partially update your authorization model
      operationId: schemas.partial-write
      parameters:
        - name: tenant_id
          description: >-
            tenant_id is a string that identifies the tenant. It must match the
            pattern "[a-zA-Z0-9-,]+",

            be a maximum of 64 bytes, and must not be empty.
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PartialWriteBody'
        required: true
      responses:
        '200':
          description: A successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SchemaPartialWriteResponse'
        default:
          description: An unexpected error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Status'
components:
  schemas:
    PartialWriteBody:
      type: object
      properties:
        metadata:
          $ref: '#/components/schemas/SchemaPartialWriteRequestMetadata'
        partials:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Partials'
          title: Map of entity name with the values needed to be updated
      title: >-
        It contains the tenant_id to identify the tenant and metadata of the
        schema to be edited,

        with the corresponding edits to various entities
    SchemaPartialWriteResponse:
      type: object
      properties:
        schema_version:
          type: string
          description: >-
            schema_version is the string that identifies the version of the
            written schema.
      description: >-
        SchemaPartialWriteResponse is the response message for the Parietal
        Write method in the Schema service.

        It returns the requested schema.
    Status:
      type: object
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
        details:
          type: array
          items:
            $ref: '#/components/schemas/Any'
    SchemaPartialWriteRequestMetadata:
      type: object
      properties:
        schema_version:
          type: string
          description: >-
            schema_version is the string that identifies the version of the
            schema to be read.
      description: >-
        SchemaPartialWriteRequestMetadata provides additional information for
        the Schema Partial Write request.

        It contains schema_version to specify which version of the schema should
        be read.
    Partials:
      type: object
      properties:
        write:
          type: array
          items:
            type: string
        delete:
          type: array
          items:
            type: string
        update:
          type: array
          items:
            type: string
      title: Partials contains the write, update and delete definitions
    Any:
      type: object
      properties:
        '@type':
          type: string
          description: >-
            A URL/resource name that uniquely identifies the type of the
            serialized

            protocol buffer message. This string must contain at least

            one "/" character. The last segment of the URL's path must represent

            the fully qualified name of the type (as in

            `path/google.protobuf.Duration`). The name should be in a canonical
            form

            (e.g., leading "." is not accepted).


            In practice, teams usually precompile into the binary all types that
            they

            expect it to use in the context of Any. However, for URLs which use
            the

            scheme `http`, `https`, or no scheme, one can optionally set up a
            type

            server that maps type URLs to message definitions as follows:


            * If no scheme is provided, `https` is assumed.

            * An HTTP GET on the URL must yield a [google.protobuf.Type][]
              value in binary format, or produce an error.
            * Applications are allowed to cache lookup results based on the
              URL, or have them precompiled into a binary to avoid any
              lookup. Therefore, binary compatibility needs to be preserved
              on changes to types. (Use versioned type names to manage
              breaking changes.)

            Note: this functionality is not currently available in the official

            protobuf release, and it is not used for type URLs beginning with

            type.googleapis.com. As of May 2023, there are no widely used type
            server

            implementations and no plans to implement one.


            Schemes other than `http`, `https` (or the empty scheme) might be

            used with implementation specific semantics.
      additionalProperties: {}
      description: >-
        `Any` contains an arbitrary serialized protocol buffer message along
        with a

        URL that describes the type of the serialized message.


        Protobuf library provides support to pack/unpack Any values in the form

        of utility functions or additional generated methods of the Any type.


        Example 1: Pack and unpack a message in C++.

            Foo foo = ...;
            Any any;
            any.PackFrom(foo);
            ...
            if (any.UnpackTo(&foo)) {
              ...
            }

        Example 2: Pack and unpack a message in Java.

            Foo foo = ...;
            Any any = Any.pack(foo);
            ...
            if (any.is(Foo.class)) {
              foo = any.unpack(Foo.class);
            }
            // or ...
            if (any.isSameTypeAs(Foo.getDefaultInstance())) {
              foo = any.unpack(Foo.getDefaultInstance());
            }

         Example 3: Pack and unpack a message in Python.

            foo = Foo(...)
            any = Any()
            any.Pack(foo)
            ...
            if any.Is(Foo.DESCRIPTOR):
              any.Unpack(foo)
              ...

         Example 4: Pack and unpack a message in Go

             foo := &pb.Foo{...}
             any, err := anypb.New(foo)
             if err != nil {
               ...
             }
             ...
             foo := &pb.Foo{}
             if err := any.UnmarshalTo(foo); err != nil {
               ...
             }

        The pack methods provided by protobuf library will by default use

        'type.googleapis.com/full.type.name' as the type URL and the unpack

        methods only use the fully qualified type name after the last '/'

        in the type URL, for example "foo.bar.com/x/y.z" will yield type

        name "y.z".


        JSON

        ====

        The JSON representation of an `Any` value uses the regular

        representation of the deserialized, embedded message, with an

        additional field `@type` which contains the type URL. Example:

            package google.profile;
            message Person {
              string first_name = 1;
              string last_name = 2;
            }

            {
              "@type": "type.googleapis.com/google.profile.Person",
              "firstName": <string>,
              "lastName": <string>
            }

        If the embedded message type is well-known and has a custom JSON

        representation, that representation will be embedded adding a field

        `value` which holds the custom JSON in addition to the `@type`

        field. Example (for message [google.protobuf.Duration][]):

            {
              "@type": "type.googleapis.com/google.protobuf.Duration",
              "value": "1.212s"
            }

````