Session policies
Attach policies to one session to narrow what it can do, and see where they are applied today.
On this page
What a session policy is
A session policy is a policy document attached to one session in your organization. It can only narrow: while a session has session policies, an action is allowed in that session only if at least one of its session policies allows the action and none denies it, on top of everything else that is required. A session policy never grants anything.
A session is identified by the sid claim of an access token:
| Token | Session ID |
|---|---|
| A person's access token | Created when they sign in to Hexel Studio, and kept when the access token is refreshed. A new sign-in starts a new session. |
| A service user's access token (API key or OAuth client) | Starts with svc_. It is derived from the credential and changes every 15 minutes. |
| A role session | Starts with rs_. Session policies never apply to role sessions. |
See Tokens for the claims of an access token.
Where session policies are applied
| Decision | Session policies applied? |
|---|---|
| Your normal API calls | No |
POST /v1/authz/evaluate, /simulate and /explain with session_id | Yes |
| Role sessions | No |
When they apply, the evaluator reads every session policy of the session in your organization:
- If the session has none, nothing changes.
- If any session policy has a Deny statement matching the action, the answer is denied with reason
session_policy_denied. - If no session policy has an Allow statement matching the action, the answer is denied with reason
session_policy_denied. - A session policy whose document cannot be read allows nothing.
Session policies are checked before the policies that grant access, so they also limit ABAC rules. Only the Action of each statement is matched: Resource and Condition are ignored.
Attach a session policy
POST /v1/session-policies/{session_id}/policies needs iam:relation:write.
| Field | Type | Description |
|---|---|---|
name | string | Name of the session policy. |
document | string | Required. A policy document, encoded as a JSON string. It needs at least one statement, and every statement needs Effect (Allow or Deny), a non-empty Action and a Resource. |
curl -X POST https://api.hexelstudio.com/v1/session-policies/<session-id>/policies \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "read-only",
"document": "{\"Version\": \"2026-02-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"workspace:workspace:read\"], \"Resource\": \"*\"}]}"
}'The response is 201 Created:
{
"id": "sp_...",
"session_id": "<session-id>",
"organization_id": "<org-id>",
"name": "read-only",
"document": "{\"Version\": \"2026-02-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"workspace:workspace:read\"], \"Resource\": \"*\"}]}",
"created_at": "2026-10-20T09:00:00Z"
}An invalid document answers 400 with the problems found:
{"error": "session policy document is not valid: statement[0]: missing 'Resource'"}Hexel Studio does not check that the session exists or belongs to someone in your organization. The session policy is stored in your organization and applies only to decisions made in your organization.
List and delete
| Call | Permission | Response |
|---|---|---|
GET /v1/session-policies/{session_id}/policies | iam:relation:read | Array of the session's session policies in your organization |
DELETE /v1/session-policies/{session_id}/policies/{policy_id} | iam:relation:write | 204, or 404 |
See the effect in the full evaluator
Pass the session ID to POST /v1/authz/evaluate to see what the full evaluator decides in that session. It needs iam:authz:simulate. See Test access for the rest of this API.
curl -X POST https://api.hexelstudio.com/v1/authz/evaluate \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"subject_id": "<user-id>",
"organization_id": "'"$ORG_ID"'",
"session_id": "<session-id>",
"action": "workspace:workspace:delete"
}'{
"allowed": false,
"reason": "session_policy_denied",
"cacheable": true,
"principal": "<user-id>",
"action": "workspace:workspace:delete",
"resource_type": "",
"workspace_id": "",
"environment_id": "",
"evaluation_ms": 4
}The same member calling DELETE /v1/workspaces/... for real is not stopped by the session policy.