Platform
Manage organizations, projects, and tokens. All Platform endpoints require a session token from /api/auth/sign-in/email.
Organizations
Organizations are the top-level container for projects, billing, and team members. Every user belongs to at least one org. All Platform endpoints require Authorization: Bearer <session_token> obtained from /api/auth/sign-in/email.
List Organizations
GET
typescript
const orgs = await ss.core.orgs.list()
- Open Dashboard
- Your organizations are listed in the sidebar
Create Organization
GET
typescript
const org = await ss.core.orgs.create({ name: 'Acme Corp' })
- Open Dashboard
- Click Create Organization
- Enter a name and click Create
Body field
Type
Description
name requiredstring
Organization name (min 1 char)
slugstring
URL-friendly slug. Lowercase alphanumeric and hyphens only (
/^[a-z0-9-]+$/). Auto-generated if omitted.Get Organization
GET
typescript
const org = await ss.core.orgs.get('org_01JNXS...')
- Open Dashboard
- Click on the organization name in the sidebar to view its details
Path param
Type
Description
org_id requiredstring
Organization ID
Update Organization
GET
typescript
await ss.core.orgs.update('org_01JNXS...', { name: 'Acme Inc' })
- Open Dashboard → select your organization
- Go to Settings and update the organization name
Path param
Type
Description
org_id requiredstring
Organization ID
Body field
Type
Description
namestring
Updated organization name
slugstring
Updated URL slug (
/^[a-z0-9-]+$/)Delete Organization
GET
typescript
await ss.core.orgs.delete('org_01JNXS...')
- Open Dashboard → select your organization
- Go to Settings → Danger Zone → Delete Organization
Path param
Type
Description
org_id requiredstring
Organization ID
Body field
Type
Description
confirm_name requiredstring
Type the org name to confirm deletion
Members
Manage organization members and their scoped permissions.
List Members
GET
typescript
const members = await ss.core.orgs.listMembers('org_01JNXS...')
- Open Dashboard → select your organization
- Go to Members to see all team members and their roles
Path param
Type
Description
org_id requiredstring
Organization ID
Invite Member
GET
typescript
await ss.core.orgs.invite('org_01JNXS...', {
email: 'alice@acme.com',
scopes: ['kv:read', 'kv:write', 'channels:publish'],
})
- Open Dashboard → select your organization
- Go to Members → click Invite
- Enter the email address and select permissions
Path param
Type
Description
org_id requiredstring
Organization ID
Body field
Type
Description
email requiredstring
Email address to invite
scopesarray
Permission scopes to grant (e.g.
["kv:read", "kv:write"])project_idstring
Restrict scopes to a specific project
Get My Scopes
GET
typescript
const scopes = await ss.core.orgs.myScopes('org_01JNXS...')
- Open Dashboard → select your organization
- Go to Members → your scopes are shown next to your name
Path param
Type
Description
org_id requiredstring
Organization ID
Update Member Scopes
GET
typescript
await ss.core.orgs.updateMemberScopes('org_01JNXS...', 'u_123', {
scopes: ['kv:read', 'channels:subscribe'],
})
- Open Dashboard → select your organization
- Go to Members → click on a member
- Update their scopes and click Save
Path param
Type
Description
org_id requiredstring
Organization ID
user_id requiredstring
User ID of the member
Body field
Type
Description
scopes requiredarray
New scopes array (replaces existing scopes)
Remove Member
GET
typescript
await ss.core.orgs.removeMember('org_01JNXS...', 'u_123')
- Open Dashboard → select your organization
- Go to Members → click on a member → Remove
Path param
Type
Description
org_id requiredstring
Organization ID
user_id requiredstring
User ID to remove
Projects
Projects live inside organizations and isolate KV namespaces, channels, jobs, and token balances.
List Projects
GET
typescript
const projects = await ss.core.orgs.listProjects('org_01JNXS...')
- Open Dashboard → select your organization
- Go to Projects to see all projects
Path param
Type
Description
org_id requiredstring
Organization ID
Create Project
GET
typescript
const project = await ss.core.orgs.createProject('org_01JNXS...', { name: 'Production' })
- Open Dashboard → select your organization
- Go to Projects → click Create Project
- Enter a name and click Create
Path param
Type
Description
org_id requiredstring
Organization ID
Body field
Type
Description
name requiredstring
Project name (min 1 char)
descriptionstring
Project description
regionstring
Region:
wnam, enam, weur, eeur, apac, oc, afr, me. Default enam.Get Project
GET
typescript
const project = await ss.core.orgs.getProject('org_01JNXS...', 'proj_01JNXS...')
- Open Dashboard → select your organization
- Go to Projects and click on any project to view its details
Path param
Type
Description
org_id requiredstring
Organization ID
project_id requiredstring
Project ID
Delete Project
GET
typescript
await ss.core.orgs.deleteProject('org_01JNXS...', 'proj_01JNXS...')
- Open Dashboard → select your project
- Go to Settings → Danger Zone → Delete Project
Path param
Type
Description
org_id requiredstring
Organization ID
project_id requiredstring
Project ID
Tokens
Create and manage project API keys with scoped permissions.
List Tokens
GET
typescript
const tokens = await ss.core.orgs.listTokens('org_01JNXS...')
- Open Dashboard → select your project
- Go to Tokens to see all API keys and their scopes
Path param
Type
Description
org_id requiredstring
Organization ID
Query param
Type
Description
project_idstring
Filter tokens by project
Create Token
GET
typescript
const token = await ss.core.orgs.createToken({
org_id: 'org_01JNXS...',
project_id: 'proj_01JNXS...',
name: 'Production Key',
scopes: ['kv:read', 'kv:write', 'channels:publish'],
})
- Open Dashboard → select your project
- Go to Tokens → click Create Token
- Name your token, select scopes, and click Create
- Copy the
sk_live_...secret — it's shown only once
Path param
Type
Description
org_id requiredstring
Organization ID
Body field
Type
Description
name requiredstring
Token display name (min 1 char)
scopes requiredarray
Permission scopes (e.g.
["kv:read", "kv:write"])project_idstring
Scope token to a specific project
expires_atstring
ISO 8601 expiration datetime
Revoke Token
GET
typescript
await ss.core.orgs.revokeToken('org_01JNXS...', 'tok_01JNXS...')
- Open Dashboard → select your project
- Go to Tokens → click on a token → Revoke
Path param
Type
Description
org_id requiredstring
Organization ID
token_id requiredstring
Token ID to revoke
Create Browser Token
GET
curl
curl -X POST https://api.saasignal.saastemly.com/core/tokens/browser \
-H "Authorization: Bearer sk_live_abc123..." \
-H "Content-Type: application/json" \
-d '{ "scopes": ["channels:subscribe", "kv:read"], "ttl": 900 }'
json — 200 OK
{
"token": "bt_eyJhbGciOi...",
"expires_at": "2026-03-10T13:15:00Z",
"ttl": 900,
"scopes": ["channels:subscribe", "kv:read"],
"project_id": "proj_01JNXS...",
"org_id": "org_01JNXS..."
}
typescript
const { token, expires_at } = await SaaSignalClient.createBrowserToken({
apiKey: 'sk_live_abc123...',
scopes: ['channels:subscribe', 'kv:read'],
ttl: 900,
})
// token is a short-lived bt_* JWT safe for browser use
- Browser tokens are created programmatically via the API or SDK — exchange a server-side
sk_live_*key for a short-livedbt_*token safe for browser use - Call
SaaSignalClient.createBrowserToken()from your server, then pass the token to your frontend
Body field
Type
Description
scopesarray
Permission scopes for the browser token (must be a subset of the parent API key's scopes). If omitted, inherits all parent key scopes.
ttlinteger
Time-to-live in seconds (default 900, min 60, max 1800)