Authentication
NoLag has two kinds of credential, and they are not interchangeable:
| Credential | Used for | Where it goes |
|---|---|---|
| API key | Managing resources over the REST API: apps, rooms, actors | Your backend or a setup script |
| Access token | Connecting a client to the broker over WebSocket | The client, or a backend service |
| Client token | Connecting an untrusted browser or mobile client | Minted per session by your backend |
API Keys
An API key authenticates calls to the REST API at
https://api.nolag.app/v1. It is the one credential you create by hand, and it is
the bootstrap secret for scripted or agent-driven setup.
API keys are project-scoped, so the key itself determines which project's resources you can reach and no organization or project id appears in the URL.
Creating an API Key
- Log in to the NoLag Dashboard.
- Open your project and go to API Keys.
- Create a key and copy it immediately. The secret half is shown only once.
Key Format
nlg_live_{keyId}.{secret}
Live keys are prefixed nlg_live_, sandbox keys nlg_sandbox_. Send the whole
string, including the dot and the secret, as a bearer token:
curl https://api.nolag.app/v1/apps \
-H "Authorization: Bearer nlg_live_xxx.secret"
An API key can create and delete every app, room, and actor in its project. Keep it on a server, never in a browser, mobile binary, or public repository.
Access Tokens
Access tokens are used to authenticate your clients with NoLag. Each token is associated with an Actor (user, device, or server) and determines what topics they can access.
Obtaining Tokens
- Log in to the NoLag Dashboard
- Navigate to your project
- Go to Actors section
- Create a new Actor or select an existing one
- Copy the access token (shown only once on creation)
Using Access Tokens
import { NoLag } from '@nolag/js-sdk'
// Using an access token
const client = NoLag('your_access_token')
await client.connect()
console.log('Authenticated and connected!')Client Tokens (Browser and Mobile)
Access tokens are long-lived, so they belong on servers, not in browsers. For untrusted clients, your backend mints a short-lived JWT (a client token) signed with a project-level signing key, and the browser connects with that instead:
import { NoLag } from '@nolag/js-sdk'
// The SDK calls your endpoint for a fresh token on every connect
const client = NoLag(async () => {
const res = await fetch('/api/nolag-token')
const { token } = await res.json()
return token
})
await client.connect()
The client token names an actor and expires within minutes; all permissions still resolve from the actor. See the full guide: Client Tokens.
Actor Types
Every actor is created with an actorType. It describes what the connection is,
which makes actors easier to filter and audit — and for two of them it also
changes how the broker treats the connection:
actorType | Use for | Session |
|---|---|---|
device | Browsers, mobile apps, IoT hardware | clean |
user | Authenticated end users | clean |
service | Backend services and microservices | clean |
session | Short-lived or temporary connections | clean |
agent | Autonomous LLM-powered connections | persists |
orchestrator | Coordination actors that dispatch work across agents | persists |
observer | Read-only audit and monitoring connections | clean |
Permissions come from the actor's topic access, not from its type. See Access Control.
Why the session column matters
agent and orchestrator connections hold a persistent session. When one
disconnects, the broker keeps its subscriptions and queues messages for it, so a
worker that goes away finds its work waiting when it comes back. That is what
makes an agent that scales to zero — or is woken by a webhook — workable.
It has two consequences worth knowing before you pick a type.
A session belongs to a client instance, not to a credential. Two processes
sharing one agent token are two attempts at the same session: the first keeps a
resumable one and the rest get clean sessions instead. If you want several
concurrent workers under one token to each keep their own, give each a stable
clientId:
const client = NoLag(token, { clientId: process.env.WORKER_NAME })Sessions expire on the plan's session window. A subscription left behind by a persistent connection survives until then, so an agent that reconnects under a different load-balance group name can briefly belong to both.
If you do not want any of this — a per-request connection, a browser, a
short-lived job — use service, session or device. They connect clean, any
number of them can share a token concurrently, and nothing is retained when they
go.
Security Best Practices
- Never ship an access token to a browser - Mint short-lived client tokens on your backend instead
- Rotate tokens regularly - Especially for production environments
- Use least privilege - Only grant necessary permissions to each Actor
- Monitor usage - Check the dashboard for unusual activity