Session tokens provide temporary, policy-restricted access to StackOne APIs without exposing your API keys in frontend code or external systems.
Overview
Session tokens let you:
Restrict API access - Define exactly which endpoints and operations the token can access
Secure frontend integrations - Use tokens in client-side code without exposing API keys
Scope by account - Limit tokens to specific linked accounts or providers
Control duration - Set expiration times for token validity
Generate session tokens server-side using your API key , then pass them to frontend code, webhooks, or third-party systems.
How Session Tokens Work
Create token server-side
Your backend calls the StackOne API with your API key and a policy definition
Receive scoped token
StackOne returns a session token restricted by your policy
Use token in restricted context
Pass the token to frontend code, webhooks, or external systems where API keys shouldn’t be exposed
Token enforces policy
The session token only allows the operations defined in your policy
Policy-Based Restrictions
Session tokens use the scopes field to define granular access control policies. Each permission rule uses glob patterns to match resources.
Permission Structure
{
"scopes" : {
"accountIds" : [ "acc_123" , "acc_456" ],
"permissions" : [
{
"id" : "read-users" ,
"effect" : "allow" ,
"tools" : [ "read-*" , "list-*" ]
},
{
"id" : "specific-accounts" ,
"effect" : "allow" ,
"accounts" : [ "acc_*_production" ]
}
]
}
}
Permission Fields
Field Type Description idstring Unique identifier for the permission rule effect”allow” | “deny” Whether to allow or deny matched resources toolsstring[] Glob patterns for tool names (e.g., "read-*", "*-users") operationstring[] Glob patterns for operation names accountsstring[] Glob patterns for account IDs
Each permission rule must specify exactly one of: tools, operation, or accounts. All rules are deny-by-default - you must explicitly allow access.
Glob Pattern Examples
// Allow all read operations
{ "effect" : "allow" , "tools" : [ "read-*" ] }
// Allow specific operations
{ "effect" : "allow" , "tools" : [ "read-users" , "read-departments" ] }
// Deny write operations
{ "effect" : "deny" , "tools" : [ "write-*" , "delete-*" ] }
// Complex patterns
{ "effect" : "allow" , "tools" : [ "{read,list}-{users,posts}" ] }
// Account patterns
{ "effect" : "allow" , "accounts" : [ "acc_*_production" ] }
Session Configuration
Additional fields control session behavior:
Field Type Default Description expires_innumber 1800 Token validity in seconds providerstring - Restrict to specific provider (e.g., “bamboohr”) account_idstring - Limit access to a single account sharedboolean true Whether account can be used by multiple end users type”test” | “production" "production” Test accounts auto-expire after 90 days metadataobject - Custom metadata (max 1MB)
Policies are defined when creating the session token. Once created, a token’s permissions cannot be expanded - you must generate a new token with broader permissions.
Creating Session Tokens
API Endpoint
Create session tokens via the POST /sessions endpoint:
import { StackOne } from "@stackone/stackone-client-ts" ;
const stackOne = new StackOne ({
security: {
username: process . env . STACKONE_API_KEY ,
password: "" ,
},
});
// Create session with scoped permissions
const result = await stackOne . sessions . create ({
tenantId: "customer-123" ,
tenantName: "Acme Inc" ,
endUserId: "user@example.com" ,
provider: "bamboohr" ,
expiresIn: 3600 , // 1 hour
scopes: {
permissions: [
{
id: "read-only" ,
effect: "allow" ,
tools: [ "read-*" , "list-*" ]
}
]
}
});
const token = result . sessionToken . token ;
from stackone_client import StackOne
client = StackOne(
api_key_auth = os.environ[ "STACKONE_API_KEY" ]
)
# Create session with scoped permissions
result = client.sessions.create(
tenant_id = "customer-123" ,
tenant_name = "Acme Inc" ,
end_user_id = "user@example.com" ,
provider = "bamboohr" ,
expires_in = 3600 , # 1 hour
scopes = {
"permissions" : [
{
"id" : "read-only" ,
"effect" : "allow" ,
"tools" : [ "read-*" , "list-*" ]
}
]
}
)
token = result.session_token.token
curl -X POST https://api.stackone.com/sessions \
-H "Authorization: Basic $( echo -n 'v1.eu1.xxx:' | base64 )" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "customer-123",
"tenant_name": "Acme Inc",
"end_user_id": "user@example.com",
"provider": "bamboohr",
"expires_in": 3600,
"scopes": {
"permissions": [
{
"id": "read-only",
"effect": "allow",
"tools": ["read-*", "list-*"]
}
]
}
}'
Common Use Cases
Read-only access to all tools
Access to specific accounts only
{
"scopes" : {
"accountIds" : [ "acc_123" , "acc_456" ],
"permissions" : [
{
"id" : "allow-all" ,
"effect" : "allow" ,
"tools" : [ "*" ]
}
]
}
}
{
"scopes" : {
"permissions" : [
{
"id" : "deny-writes" ,
"effect" : "deny" ,
"tools" : [ "write-*" , "update-*" , "delete-*" ]
},
{
"id" : "allow-reads" ,
"effect" : "allow" ,
"tools" : [ "*" ]
}
]
}
}
Using Session Tokens
After creating a session token, use it in place of your API key for authentication:
# Using API key
curl -X GET https://api.stackone.com/accounts \
-H "Authorization: Basic $( echo -n 'v1.eu1.xxx:' | base64 )"
# Using session token
curl -X GET https://api.stackone.com/accounts \
-H "Authorization: Bearer SESSION_TOKEN_HERE"
Session tokens use Bearer authentication (Authorization: Bearer TOKEN) while API keys use Basic authentication. This makes them easy to identify and rotate independently.
Managing Session Tokens
List Sessions
Retrieve all active session tokens:
curl -X GET https://api.stackone.com/sessions \
-H "Authorization: Basic $( echo -n 'v1.eu1.xxx:' | base64 )"
Get Session Details
Retrieve information about a specific session:
curl -X GET https://api.stackone.com/sessions/{session_id} \
-H "Authorization: Basic $( echo -n 'v1.eu1.xxx:' | base64 )"
Update Session Permissions
Modify the scopes of an existing session:
curl -X PATCH https://api.stackone.com/sessions/{session_id} \
-H "Authorization: Basic $( echo -n 'v1.eu1.xxx:' | base64 )" \
-H "Content-Type: application/json" \
-d '{
"scopes": {
"permissions": [
{
"id": "updated-permissions",
"effect": "allow",
"tools": ["read-*"]
}
]
}
}'
Revoke Session
Immediately invalidate a session token:
curl -X DELETE https://api.stackone.com/sessions/{session_id} \
-H "Authorization: Basic $( echo -n 'v1.eu1.xxx:' | base64 )"
Revoking a session immediately invalidates the token. Any API calls using that token will fail with a 401 error.
Customizing the Hub Behavior