Search docs ⌘K
esc
Type to search across all documentation pages

Quick Start

From zero to a working integration in under 5 minutes.

1

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:

.env
SAASIGNAL_KEY=sk_live_your_key_here
2

Store a value in KV

curl
curl -X PUT https://api.saasignal.saastemly.com/infra/kv/hello \
  -H "Authorization: Bearer $SAASIGNAL_KEY" \
  -H "Content-Type: application/json" \
  -d '{"value": "world"}'
3

Read it back

curl
curl https://api.saasignal.saastemly.com/infra/kv/hello \
  -H "Authorization: Bearer $SAASIGNAL_KEY"
# {"key": "hello", "value": "world", "expires_at": null}
4

Publish a real-time event

curl
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"}}'
Full API reference: Explore all endpoints interactively at api.saasignal.saastemly.com/scalar (Scalar API Reference).
1

Install the SDK

terminal
npm install saasignal
2

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:

.env.local
SAASIGNAL_KEY=sk_live_your_key_here
3

Initialize the client

lib/saasignal.ts
import { createClient } from 'saasignal'

export const ss = createClient(process.env.SAASIGNAL_KEY!)
4

Make your first call

Store something in KV from an API route:

app/api/session/route.ts
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 })
}
CLI login: The 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.
1

Sign up

Go to saasignal.saastemly.com/auth/sign-up and create your account.

2

Create an organization

From the Dashboard, click Create Organization. Every org has its own billing and token balance.

3

Create a project

Inside your org, go to Projects and create a new project. Projects isolate KV namespaces, channels, and job queues.

4

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.

5

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.

Dashboard features: The Dashboard lets you browse KV keys, publish channel messages, create and monitor jobs, view usage, and manage billing — all without writing code.

Authentication

Core layer — Project tokens

All KV, Channels, and Jobs endpoints require a project token passed as a Bearer token:

http
curl https://api.saasignal.saastemly.com/infra/kv/mykey \
  -H "Authorization: Bearer sk_live_abc123..."
typescript
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

Scope
Grants access to
kv:read
GET /infra/kv/:key, GET /infra/kv (scan)
kv:write
PUT, DELETE, POST /infra/kv/:key/increment, POST /infra/kv (batch)
locks:read
GET /infra/locks/:key
locks:write
POST /infra/locks/:key/acquire, /release, /renew
sketches:read
GET HLL counts and CMS estimates
sketches:write
POST HLL add/merge and CMS increment endpoints
channels:publish
POST /infra/channels/:channel/publish, batch publish
channels:subscribe
GET subscribe, presence, history
jobs:read
GET /infra/jobs, GET /infra/jobs/:id, GET /infra/jobs/:id/runs
jobs:write
POST /infra/jobs, batch, claim, PATCH, DELETE, ack, trigger, retry
workflows:read
GET workflow blueprints and execution status
workflows:write
Create blueprints, trigger executions, cancel, and resume workflows
webhooks:read
GET /infra/webhooks, GET deliveries
webhooks:write
POST /infra/webhooks, PATCH, DELETE, test, retry delivery

Logistics

Scope
Grants access to
logistics:read
GET geo entities/nearby, geofences, tracking history, distance-matrix, isochrone, snap, geocoding
logistics:write
POST/PATCH geo entities, POST geofences, route, optimize, dispatch
logistics:admin
DELETE geo entities (deactivate), DELETE geofences
logistics:track
POST tracking pings (single and batch)

Delivery

Scope
Grants access to
delivery:read
GET orders, stops, drivers, customers, vehicles, zones, hubs, analytics, settings, notifications, webhooks
delivery:write
POST/PATCH orders, stops, drivers, customers, vehicles, zones, hubs, dispatch, settings, notifications, webhooks, export

Platform

Scope
Grants access to
orgs:read
GET organization, list members, get scopes
orgs:write
PATCH/DELETE org, invite member, update/remove member scopes
projects:read
GET /core/organizations/:id/projects
projects:write
POST/DELETE projects
tokens:read
GET /core/organizations/:id/tokens
tokens:write
POST/DELETE tokens (API keys)
billing:read
GET subscription, usage dashboard, token balance, token usage

Browser 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:

http
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 }'
typescript
// 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:

http
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.

Keep API keys server-side. Never expose 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.

KV read
~1.25M / token
GET /infra/kv/:key
KV write
~189K / token
PUT /infra/kv/:key
KV delete
~189K / token
DELETE /infra/kv/:key
Channel publish
~2.2M / token
per message/channel
Channel subscribe
~500K mins / token
per connection-minute
Job create
~555K / token
POST /infra/jobs
Job execution
~555K / token
per trigger/delivery

Check remaining balance:

curl
curl "https://api.saasignal.saastemly.com/core/tokens/balance?org_id=org_123" \
  -H "Authorization: Bearer <session_token>"
typescript
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.

json — response
{
  "org_id": "org_123",
  "included_remaining": 3.42,
  "topup_balance": 1.40,
  "total": 4.82
}