Quick Start
From zero to a working integration in under 5 minutes.
Create a project and get your token
Sign in at saasignal.saastemly.com, create an org, create a project, and generate a token. Store it as an environment variable:
SAASIGNAL_KEY=sk_live_your_key_here Store a value in KV
curl -X PUT https://api.saasignal.saastemly.com/infra/kv/hello \
-H "Authorization: Bearer $SAASIGNAL_KEY" \
-H "Content-Type: application/json" \
-d '{"value": "world"}' Read it back
curl https://api.saasignal.saastemly.com/infra/kv/hello \
-H "Authorization: Bearer $SAASIGNAL_KEY"
# {"key": "hello", "value": "world", "expires_at": null} Publish a real-time event
curl -X POST https://api.saasignal.saastemly.com/infra/channels/my-channel/publish \
-H "Authorization: Bearer $SAASIGNAL_KEY" \
-H "Content-Type: application/json" \
-d '{"event": "ping", "data": {"hello": "world"}}' Install the SDK
npm install saasignal Create a project and get your token
Sign in at saasignal.saastemly.com, create an org, create a project, and generate a token with the scopes you need. Store it in your environment:
SAASIGNAL_KEY=sk_live_your_key_here Initialize the client
import { createClient } from 'saasignal'
export const ss = createClient(process.env.SAASIGNAL_KEY!) Make your first call
Store something in KV from an API route:
import { ss } from '@/lib/saasignal'
import { NextResponse } from 'next/server'
export async function POST(req: Request) {
const session = await req.json()
await ss.infra.kv.set(`session:${session.userId}`, session, { ttl: 86400 })
return NextResponse.json({ ok: true })
} saasignal package also ships a CLI. Run npx saasignal auth login to open the frontend sign-in flow in your browser and store a scoped OAuth token locally for terminal use. API keys remain the best fit for deployed server code.
Sign up
Go to saasignal.saastemly.com/auth/sign-up and create your account.
Create an organization
From the Dashboard, click Create Organization. Every org has its own billing and token balance.
Create a project
Inside your org, go to Projects and create a new project. Projects isolate KV namespaces, channels, and job queues.
Generate a token
In your project, go to Tokens and create a token with the scopes you need (e.g. kv:read, kv:write). Copy the sk_live_... secret — it's shown only once.
Explore your data
Use the Dashboard's built-in KV browser, channel monitor, and job inspector to manage your data visually. Navigate via the sidebar: Dashboard → select a project → use the primitives tabs.
Authentication
Core layer — Project tokens
All KV, Channels, and Jobs endpoints require a project token passed as a Bearer token:
curl https://api.saasignal.saastemly.com/infra/kv/mykey \
-H "Authorization: Bearer sk_live_abc123..." import { createClient } from 'saasignal'
// Reads SAASIGNAL_TOKEN or SAASIGNAL_API_KEY from env automatically if no arg passed
const ss = createClient('sk_live_abc123...')
// Or set SAASIGNAL_API_KEY in your environment:
const ss2 = createClient() In the Dashboard, authentication is handled automatically via your session. Just sign in and navigate to your project. Tokens can be created and managed from the Dashboard → Project → Tokens section.
Tokens are scoped per-project and per-capability. The wildcard scope * grants access to all routes. Resource wildcards (e.g. kv:*) grant all actions on that resource. Available scopes:
Infrastructure
kv:readkv:writelocks:readlocks:writesketches:readsketches:writechannels:publishchannels:subscribejobs:readjobs:writeworkflows:readworkflows:writewebhooks:readwebhooks:writeLogistics
logistics:readlogistics:writelogistics:adminlogistics:trackDelivery
delivery:readdelivery:writePlatform
orgs:readorgs:writeprojects:readprojects:writetokens:readtokens:writebilling:readBrowser tokens
API keys (sk_live_) must never be exposed in client-side code. For browser-safe access, exchange an API key for a short-lived browser token (bt_*) via a server-side call:
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 }' // Server-side: create a browser token for the client
const { token, expires_at } = await SaaSignalClient.createBrowserToken({
apiKey: 'sk_live_abc123...',
scopes: ['channels:subscribe', 'kv:read'],
ttl: 900,
})
// Send `token` (bt_...) to the browser — it's safe to expose Browser tokens are short-lived JWTs (default 15 minutes, max 30 minutes). They carry only the scopes you specify, which must be a subset of the parent API key's scopes. Use them in client-side JavaScript wherever you would otherwise need an API key — for example, subscribing to channels or reading KV data from the browser.
Platform layer — User JWT
Dashboard-type operations (managing orgs, projects, billing) use a session token obtained by signing in:
POST /api/auth/sign-in/email
Content-Type: application/json
{ "email": "you@acme.com", "password": "..." } The response includes a token field. Use it as Authorization: Bearer <token> for Platform routes. Better Auth also sets a session cookie automatically for browser clients.
sk_live_ tokens in client-side JavaScript. For browser use, exchange your API key for a short-lived browser token (bt_*) via POST /core/tokens/browser — see Browser tokens above.
Token Model
1 token ≈ $1 of metered SaaSignal platform spend. Billing tracks underlying compute, storage, media, realtime, and logistics provider cost as closely as the platform can observe it. Every metered API response includes an X-Microtokens-Used header showing the token cost of that request.
Check remaining balance:
curl "https://api.saasignal.saastemly.com/core/tokens/balance?org_id=org_123" \
-H "Authorization: Bearer <session_token>" const balance = await ss.core.billing.tokenBalance('org_123')
console.log(balance.total) // 4.82 In the Dashboard, go to Usage to see your current token balance, usage breakdown by primitive, and billing cycle details.
{
"org_id": "org_123",
"included_remaining": 3.42,
"topup_balance": 1.40,
"total": 4.82
}