Skip to content

Channel Access Control

Channel entries can be protected at two levels:

  • The channel ACL sets the default rule for every entry in the channel.
  • The entry ACL can grant or deny access for one specific row.

The entry ACL wins when it explicitly grants an action. A row-level deny also vetoes the channel default, so an entry can stay hidden even when the channel is public.

Channel ACL

The channel acl object accepts one scope for each action:

json
{
  "acl": {
    "create": "shared",
    "read": "public",
    "update": "private",
    "delete": "private"
  }
}
ScopeMeaning
publicAnyone can pass this action, including anonymous visitors.
sharedAny signed-in customer can pass this action.
privateFor read, update, and delete: only the entry owner can pass. For create: any signed-in customer can create.
noneThe channel does not grant the action. A row ACL can still grant access to a specific entry.

For entries, the owner is stored in _owner. Private read, update, and delete checks compare _owner with the current customer id.

Entry ACL

The entry _acl object is keyed by actor:

json
{
  "_owner": "65f0c6f2c2f48f7a2d1a1111",
  "_acl": {
    "*": { "read": true },
    "users": { "update": false },
    "id:65f0c6f2c2f48f7a2d1a1111": { "read": true, "update": true },
    "role:members": { "read": true }
  }
}

Actor keys:

Actor keyMatches
*Everyone for grants. For denies, it blocks anonymous access and public channel defaults.
usersAny signed-in customer.
id:<customer_id>One customer.
role:<role_name>Customers assigned to that role.

Action values are booleans. true grants the action. false denies it. For signed-in customers, use users, id:<customer_id>, or role:<role_name> when you want a deny rule to match them. The API stores negative rules internally as noRead, noUpdate, and noDelete, but clients should send the public shape above.

How Checks Resolve

For read, update, and delete, Nimbu evaluates access in this order:

  1. If the entry has a positive row-level grant for the action, the current actor must match it.
  2. If there is no positive row-level grant, the channel ACL decides the default.
  3. A matching row-level deny vetoes both cases.

That means:

  • A channel with read: public can hide one entry with { "*": { "read": false } }.
  • A channel with read: shared can hide one entry from all signed-in customers with { "users": { "read": false } }.
  • A channel with read: private can still hide an entry from its owner with { "id:<customer_id>": { "read": false } }.
  • A channel with read: none can expose one row with a positive row grant such as { "role:members": { "read": true } }.

REST API Filtering

Channel entry routes apply ACLs for non-master tokens. Master tokens bypass ACLs unless you opt in:

http
GET /channels/articles/entries?use_acl=true
Authorization: Bearer <master-token>
Session-Token: <customer-session-token>

Use Session-Token or X-Nimbu-Session-Token to evaluate the request as a customer. Customer OAuth tokens also resolve the current customer. If no customer can be resolved, ACL checks run as anonymous.

Hidden single entries return 404, not 403. Collection and count routes filter hidden entries out of the result.

Part of Nimbu, built by Zenjoy.