Appearance
Staff roles and permissions
Staff calls use a normal user Bearer JWT plus permission checks; there is no separate Platform staff API key. Prerequisites: an operator with roles.write and roles.assign, an existing target user, and apiRequest.
Create and assign a role
- Read the permission catalog via getAdminPermissionMatrix and choose the minimum keys for the workflow.
- Create a role using createAdminRole.
- Replace its permission set with setAdminRolePermissions.
- Grant it to the user through assignAdminRole.
ts
const role = await apiRequest("/v1/admin/roles", {
method: "POST", body: JSON.stringify({ key: "catalog-editor", name: "Catalog editor" }),
});
await apiRequest(`/v1/admin/roles/${role.id}/permissions`, {
method: "PUT", body: JSON.stringify({ keys: ["store.read", "store.write"] }),
});
await apiRequest("/v1/admin/roles/assign", {
method: "POST",
body: JSON.stringify({
user_id: "3f6c2a1e-8b4d-4e7a-9c1f-2d5b6a7e8f90",
role_key: "catalog-editor", reason: "Catalog publishing duties",
}),
});Replace the synthetic user ID with an existing user. Permission replacement and role assignment return 204. The assignee should obtain a fresh access token after changes and verify getMyPermissions.
Permission semantics and failures
A route requiring several keys uses OR semantics: one matching key is enough. * matches all permissions and <resource>.* matches that resource. Role membership alone is not a substitute for the operation's required keys.
json
{"error":"forbidden","details":{"perm":"announcements.write | email.send"}}This means either listed permission is accepted. A missing/expired token is 401; valid authentication without a matching permission is 403. Confirm the token belongs to the intended user, refresh it after role changes, inspect effective keys, and check the operation's Authentication section. Use revokeAdminRole to remove a grant. Bulk staff mutations return per-user results; a 200 does not mean every item succeeded.