Why use bundles
Without bundles, every service that needs to write authorization data must know the exact tuple structure. If that structure changes — a new relation is added, a naming convention shifts — every service must be updated. Bundles centralise that logic. The authorization model and the data-write templates live together in Permify, and your application services only need to callRunBundle with a name and a set of identifiers.
Defining a bundle
Use the Write Bundle API to create or update a bundle. Each bundle has:- A unique
nameused to identify and execute it. - An
argumentslist declaring the variable names the bundle accepts. - An
operationslist describing the relationships and attributes to write or delete, using{{.variableName}}template syntax.
- Write
organization:{organizationID}#admin@user:{creatorID} - Write
organization:{organizationID}#manager@user:{creatorID} - Set the attribute
organization:{organizationID}$publictofalse
Running a bundle
Use the Run Bundle API to execute a bundle by name, passing the concrete argument values.organization:789#admin@user:564organization:789#manager@user:564organization:789$public|boolean:false
RunBundle returns a snap_token representing the database state after the write. Use that token in subsequent check requests to guarantee fresh results. See Snap Tokens.
Operations
Each object in theoperations array supports four keys:
| Key | Description |
|---|---|
relationships_write | Relationships to create. Uses tuple notation: entity_type:id#relation@subject_type:id. |
relationships_delete | Relationships to delete. Same notation as relationships_write. |
attributes_write | Attributes to set. Uses attribute notation: entity_type:id$attribute|type:value. |
attributes_delete | Attributes to remove. Same notation as attributes_write. |
Bundle API endpoints
Write Bundle
Create or update one or more bundles.
Run Bundle
Execute a bundle with concrete argument values.
Read Bundle
Retrieve the definition of a bundle by name.