API Reference: Session Tokens
Create and manage short-lived, scoped session tokens (s360_sess_*) for browsers, AI agents, and partner access.
Overview
Session tokens are short-lived, scoped credentials that you mint from your server using an API key. They are designed for client-side use, AI agents, and temporary partner access — scenarios where exposing a long-lived API key would be a security risk. Every session token value starts with s360_sess_; its identifier (returned as id) starts with sess_.
Key Concepts
- Short-lived — Maximum lifetime is 24 hours (1440 minutes); the default is 60 minutes. Tokens cannot be renewed; mint a new one when they expire.
- Scoped — Each token carries a subset of the creator's feature permissions plus a set of API scopes. Scopes default to read-only:
schema:readandrecords:read. - Inherited ceiling — A token can never exceed the permissions or scopes of the API key (or user) that created it. If you omit
featurePermissions, the token inherits all of the creator's feature permissions — pass an explicit subset for least privilege. - Never admin — Session tokens never carry sysadmin or team-admin status, and full data access is only retained when the creator has it and
DATA_FULL_ACCESSis included in the token's feature permissions.
Endpoints
| Method | Path | Purpose |
|---|---|---|
POST | /v1/session-tokens | Create a session token (value returned once). |
GET | /v1/session-tokens/{sessionTokenId} | Get token metadata (never the token value). |
DELETE | /v1/session-tokens/{sessionTokenId} | Revoke a token before its natural expiry. |
Create a Session Token
Generate a scoped session token from your server using an API key, then send the token to your client. The request body accepts expiresInMinutes (1–1440, default 60), featurePermissions, oauthScopes, and free-form metadata.
TypeScript SDK
const session = await s360.sessionTokens.create({
expiresInMinutes: 60,
featurePermissions: ['DATA_RECORD_LOGS'], // subset of the caller's permissions
oauthScopes: ['schema:read', 'records:read'],
});
// session.data.token is the s360_sess_... value to send to the client (returned once).
// session.data.id is the sess_... identifier for later inspection/revocation.
console.log(`Token: ${session.data.token}`);
console.log(`Expires at: ${session.data.expiresAt}`);
cURL
curl -s -X POST "https://api.simply360.app/v1/session-tokens" \
-H "Authorization: Bearer $S360_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"expiresInMinutes": 60,
"oauthScopes": ["schema:read", "records:read"]
}'
Valid oauthScopes values are schema:read, records:read, records:write, websites:read, websites:write, conversations:read, conversations:write, files:write, wizards:run, and admin:read. Unknown scopes are rejected with 400 INVALID_OAUTH_SCOPES; requested scopes the creator does not hold are silently dropped. Request write scopes only for the capability the token needs: records:write for record mutation and files:write for the quarantined file-upload flow.
Using a Session Token
Use a session token in the same way as an API key — pass it in the Authorization: Bearer header.
// In a browser or other client environment
import { Simply360 } from '@simply360/sdk';
const s360 = new Simply360({
apiKey: tokenFromServer, // s360_sess_...
});
// Operations are limited to the token's scope
const records = await s360.dataRecords.list({ dataCollectionSimplyId: 'XXXX-XXXX-XXXX' });
curl -s "https://api.simply360.app/v1/data-records?dataCollectionSimplyId=XXXX-XXXX-XXXX" \
-H "Authorization: Bearer s360_sess_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Inspect a Session Token
Fetch metadata for a token you minted — useful for checking whether it has expired and which permissions it carries. The token value itself is never returned.
curl -s "https://api.simply360.app/v1/session-tokens/sess_1f2e3d4c5b6a7890" \
-H "Authorization: Bearer $S360_API_KEY"
{
"data": {
"id": "sess_1f2e3d4c5b6a7890",
"expiresAt": "2026-07-07T15:00:00.000Z",
"expired": false,
"featurePermissions": ["DATA_RECORD_LOGS"],
"oauthScopes": ["schema:read", "records:read"],
"metadata": null,
"createdAt": "2026-07-07T14:00:00.000Z"
}
}
Revoke a Session Token
Use revoke when you need to immediately invalidate a token before its natural expiry. Pass the sess_... identifier (not the token value).
await s360.sessionTokens.revoke('sess_1f2e3d4c5b6a7890');
curl -s -X DELETE "https://api.simply360.app/v1/session-tokens/sess_1f2e3d4c5b6a7890" \
-H "Authorization: Bearer $S360_API_KEY"
Use Cases
- Browser proxying — Issue a short-lived, read-only token to a single-page app so it can fetch data directly without exposing your API key.
- AI agents — Give an LLM-driven workflow tightly scoped credentials it cannot exceed, even if its prompt is compromised.
- Third-party access — Grant a partner temporary, scoped access without giving them a permanent API key.
- Mobile apps — Pair a backend authentication step with on-device session tokens that expire automatically.
Usage Notes
- Tokens cannot have broader feature permissions or scopes than the credential used to create them — requested extras are dropped.
- Omitting
featurePermissionsinherits every feature permission the creator holds. Always pass an explicit subset for client-facing tokens. - Tokens default to
schema:readandrecords:read. Includerecords:writeexplicitly for write-capable clients. - Expired or revoked tokens return
401 UNAUTHENTICATED. Your client should handle this by requesting a new token from your server. - Maximum lifetime is 1440 minutes (24 hours). Shorter durations are recommended for better security.
- There is no list endpoint — store the
idreturned at creation if you need to inspect or revoke tokens later.