API Rules are your collection access controls and data filters.

Each collection has 5 rules, corresponding to the specific API action:

Auth collections have an additional options.manageRule used to allow one user (it could be even from a different collection) to be able to fully manage the data of another user (ex. changing their email, password, etc.).

Each rule could be set to:

PocketBase API Rules act also as records filter!
Or in other words, you could for example allow listing only the "active" records of your collection, by using a simple filter expression such as: status = "active" (where "status" is a field defined in your Collection).

Because of the above, the API will return 200 empty items response in case a request doesn't satisfy a listRule, 400 for unsatisfied createRule and 404 for unsatisfied viewRule, updateRule and deleteRule.
All rules will return 403 in case they were "locked" (aka. superuser only) and the request client is not a superuser.

The API Rules are ignored when the action is performed by an authorized superuser (superusers can access everything)!

You can find information about the available fields in your collection API rules tab:

Collection API Rules filters screenshot

There is autocomplete to help guide you while typing the rule filter expression, but in general you have access to 3 groups of fields:

  • Your Collection schema fields
    This includes all nested relation fields too, ex. someRelField.status != "pending"
  • @request.*
    Used to access the current request data, such as query parameters, body/form fields, authorized user state, etc.
    • @request.context - the context where the rule is used (ex. @request.context != "oauth2")
      The currently supported context values are default, oauth2, otp, password, realtime, protectedFile.
    • @request.method - the HTTP request method (ex. @request.method = "GET")
    • @request.headers.* - the request headers as string values (ex. @request.headers.x_token = "test")
      Note: All header keys are normalized to lowercase and "-" is replaced with "_" (for example "X-Token" is "x_token").
    • @request.query.* - the request query parameters as string values (ex. @request.query.page = "1")
    • @request.auth.* - the current authenticated model (ex. @request.auth.id != "")
    • @request.body.* - the submitted body parameters (ex. @request.body.title != "")
      Note: Uploaded files are not part of the @request.body because they are evaluated separately (this behavior may change in the future).
  • @collection.*

    This filter could be used to target other collections that are not directly related to the current one (aka. there is no relation field pointing to it) but both shares a common field value, like for example a category id:

    In case you want to join the same collection multiple times but based on different criteria, you can define an alias by appending :alias suffix to the collection name.

The following datetime macros are available and can be used as part of the filter expression:

For example:

= @now`} />

The :isset field modifier is available only for the @request.* fields and can be used to check whether the client submitted a specific data with the request. Here is for example a rule that disallows changing a "role" field:

Note that @request.body.*:isset at the moment doesn't support checking for new uploaded files because they are evaluated separately and cannot be serialized (this behavior may change in the future).

The :length field modifier could be used to check the number of items in an array field (multiple file, select, relation).
Could be used with both the collection schema fields and the @request.body.* fields. For example:

1 // check existing record field length someRelationField:length = 2 `} />

Note that @request.body.*:length at the moment doesn't support checking for new uploaded files because they are evaluated separately and cannot be serialized (this behavior may change in the future).

The :each field modifier works only with multiple select, file and relation type fields. It could be used to apply a condition on each item from the field array. For example:

Note that @request.body.*:each at the moment doesn't support checking for new uploaded files because they are evaluated separately and cannot be serialized (this behavior may change in the future).

The :lower field modifier could be used to perform lower-case string comparisons. For example:

Under the hood it uses the SQLite LOWER scalar function and by default works only for ASCII characters, unless the ICU extension is loaded.

The geoDistance(lonA, latA, lonB, latB) function could be used to calculate the Haversine distance between 2 geographic points in kilometres.

The function is intended to be used primarily with the geoPoint field type, but the accepted arguments could be any plain number or collection field identifier. If the identifier cannot be resolved and converted to a numeric value, it resolves to null. Note that the geoDistance function always results in a single row/record value meaning that "any/at-least-one-of" type of constraint will be applied even if some of its arguments originate from a multiple relation field.

For example:

  • Allow only registered users:
  • Allow only registered users and return records that are either "active" or "pending":
  • Allow only registered users who are listed in an allowed_users multi-relation field value:
  • Allow access by anyone and return only the records where the title field value starts with "Lorem" (ex. "Lorem ipsum"):