Node SDK
API reference for @temps-sdk/node-sdk (0.0.7). The package gives server-side Node.js and Bun code two things: TempsClient, a typed client for the Temps REST API with 25 namespaces, and ErrorTracking, a Sentry-compatible client that reports exceptions to your project's DSN. It also includes a feature-flag reader.
Other SDKs (React analytics, Vue, Svelte, KV and Blob storage) are listed in SDKs; browser error tracking uses the official Sentry SDKs, as described in Error Tracking.
Installation
npm install @temps-sdk/node-sdk
Requirements: Node.js 18+ or Bun. TypeScript 5+ (peer dependency).
API client
The API client provides typed access to every Temps API endpoint. List endpoints are paginated; see Pagination.
import { TempsClient } from '@temps-sdk/node-sdk';
const temps = new TempsClient({
baseUrl: 'https://your-temps-instance.com/api',
apiKey: 'your-api-key',
});
// List projects
const { data: projects } = await temps.projects.list();
// Trigger a deployment of the main branch
await temps.projects.triggerPipeline({
path: { id: 1 },
body: { branch: 'main' },
});
// Rollback
await temps.deployments.rollback({
path: { project_id: 1, deployment_id: 5 },
});
Constructor options
- Name
baseUrl- Type
- string
- Description
Your Temps instance's API root, including the
/apiprefix (e.g.https://your-temps-instance.com/api). The client's paths, such as/projects/{id}, are appended to it. Apps deployed on Temps get this value injected asTEMPS_API_URL. Required.
- Name
apiKey- Type
- string
- Description
API key, sent as a Bearer token. Optional in the type, but every authenticated endpoint needs it.
Raw client access
For advanced use cases or endpoints not covered by namespaces:
const client = temps.rawClient;
Client namespaces
The client organizes all platform operations into 25 typed namespaces:
| Namespace | Description |
|---|---|
temps.apiKeys | API key CRUD, activate/deactivate |
temps.analytics | Visitors, sessions, events, enrichment, stats |
temps.auditLogs | Audit log retrieval |
temps.authentication | Login, logout, MFA, password reset |
temps.backups | Backup schedules, S3 sources, run/restore |
temps.crons | Cron jobs and execution history |
temps.deployments | Get, cancel, pause, resume, rollback, teardown, jobs and job logs (start a deploy with temps.projects.triggerPipeline) |
temps.dns | DNS providers, managed domains, zone listing |
temps.domains | SSL/TLS domains, ACME provisioning |
temps.email | Email providers, domains, send, stats |
temps.externalServices | PostgreSQL, Redis, S3 lifecycle, env vars |
temps.files | File retrieval by ID |
temps.funnels | Funnel CRUD, metrics, previews |
temps.git | GitHub/GitLab providers, repo connections, sync |
temps.loadBalancer | Route management |
temps.monitoring | Monitors, incidents, uptime, status buckets |
temps.notifications | Preferences, providers (email, Slack, webhook) |
temps.performance | Web Vitals metrics |
temps.platform | Instance info, IPs, geolocation, presets |
temps.projects | Full project lifecycle: environments, domains, env vars, containers, analytics, errors, session replay, webhooks |
temps.proxyLogs | Proxy log queries |
temps.repositories | Synced repos, branches, tags, presets |
temps.sessionReplay | Session init, events, deletion |
temps.settings | Platform settings |
temps.users | User CRUD, MFA, roles |
All request/response types are auto-generated from the OpenAPI spec:
import type {
ProjectResponse,
DeploymentResponse,
CreateProjectRequest,
} from '@temps-sdk/node-sdk';
Error tracking
A Sentry-compatible error tracking client for server-side code. Initialize it once at application startup. Grouping, source maps and the dashboard side are covered in Error Tracking.
import { ErrorTracking } from '@temps-sdk/node-sdk';
ErrorTracking.init({
dsn: 'https://public-key@your-instance.temps.dev/1',
environment: 'production',
release: '1.0.0',
});
The DSN follows the Sentry format: https://<public-key>@<host>/<project-id>. Find it in your project's Error Tracking > DSN & Setup tab.
ErrorTracking.init options
- Name
dsn- Type
- string
- Description
The Data Source Name. Required.
- Name
environment- Type
- string
- Description
Environment name (e.g.
production,staging).
- Name
release- Type
- string
- Description
Your application version.
- Name
serverName- Type
- string
- Description
Server identifier for distinguishing instances.
- Name
sampleRate- Type
- number
- Description
Error sampling rate (0.0 to 1.0).
- Name
tracesSampleRate- Type
- number
- Description
Performance trace sampling rate (0.0 to 1.0).
- Name
ignoreErrors- Type
- (string | RegExp)[]
- Description
Errors matching these patterns are silently dropped.
- Name
beforeSend- Type
- (event) => event | null
- Description
Modify or drop events before sending. Return
nullto drop.
- Name
maxBreadcrumbs- Type
- number
- Description
Maximum breadcrumbs to retain.
- Name
attachStacktrace- Type
- boolean
- Description
Attach stack traces to message events.
- Name
debug- Type
- boolean
- Description
Log events to console instead of sending. Useful for development.
- Name
integrations- Type
- Integration[]
- Description
Custom integrations (each must implement
setupOnce()).
Capturing errors
// Capture an exception
try {
riskyOperation();
} catch (error) {
const eventId = ErrorTracking.captureException(error);
}
// Capture with extra context
ErrorTracking.captureException(error, {
tags: { subsystem: 'payments' },
extra: { orderId: '12345', amount: 99.99 },
level: 'fatal',
});
// Capture a message
ErrorTracking.captureMessage('Disk usage above 90%', 'warning');
// Capture a raw event
ErrorTracking.captureEvent({
message: 'Custom event',
level: 'info',
tags: { source: 'cron' },
});
Global handlers
The SDK automatically captures unhandled errors:
| Handler | Level | Behavior |
|---|---|---|
process.on('uncaughtException') | fatal | Captured, then process.exit(1) |
process.on('unhandledRejection') | error | Captured, process continues |
Both are tagged with handled: false.
Context and scope
Enrich error reports with user information, tags, and structured data.
// Set the current user (attached to all subsequent events)
ErrorTracking.setUser({
id: '123',
email: 'alice@example.com',
username: 'alice',
ip_address: '{{auto}}',
});
// Set global tags
ErrorTracking.setTag('region', 'eu-west-1');
ErrorTracking.setTags({ service: 'api', version: '2.0' });
// Set extra data
ErrorTracking.setExtra('requestId', 'abc-123');
ErrorTracking.setExtras({ query: 'SELECT ...', duration: 150 });
// Set structured context
ErrorTracking.setContext('order', {
id: 'order-456',
total: 99.99,
items: 3,
});
// Clear user on logout
ErrorTracking.setUser(null);
Scoped context
// Permanent scope modification
ErrorTracking.configureScope((scope) => {
scope.setTag('transaction', 'checkout');
scope.setUser({ id: '123' });
});
// Temporary scope (discarded after callback)
ErrorTracking.withScope((scope) => {
scope.setTag('component', 'payment-form');
ErrorTracking.captureMessage('Payment processed');
});
Breadcrumbs
Leave a trail of events leading up to an error.
ErrorTracking.addBreadcrumb({
category: 'auth',
message: 'User logged in',
level: 'info',
data: { method: 'oauth' },
});
ErrorTracking.addBreadcrumb({
category: 'http',
message: 'GET /api/users',
level: 'info',
type: 'http',
data: { status: 200, duration: 45 },
});
// Clear all breadcrumbs
ErrorTracking.clearBreadcrumbs();
Breadcrumb properties
- Name
category- Type
- string
- Description
Grouping category (e.g.
auth,http,db).
- Name
message- Type
- string
- Description
Human-readable description.
- Name
type- Type
- string
- Description
One of:
default,http,navigation,console.
- Name
level- Type
- string
- Description
One of:
debug,info,warning,error,critical.
- Name
data- Type
- Record<string, any>
- Description
Arbitrary structured data.
Performance monitoring
Track transactions and spans to measure latency.
const transaction = ErrorTracking.startTransaction({
name: 'POST /api/checkout',
op: 'http.server',
});
const dbSpan = transaction.startChild({
op: 'db.query',
description: 'SELECT * FROM orders WHERE id = ?',
});
// ... query ...
dbSpan.finish();
transaction.setMeasurement('order_total', 99.99, 'usd');
transaction.setStatus('ok');
transaction.finish();
Spans capture startTimestamp, endTimestamp, op, description, status, tags, and data. Spans can be nested.
User feedback
Collect feedback after an error:
const eventId = ErrorTracking.captureException(error);
ErrorTracking.captureUserFeedback({
event_id: eventId,
name: 'Alice',
email: 'alice@example.com',
comments: 'The checkout button did nothing.',
});
Lifecycle
// Flush pending events (waits up to 2s by default)
await ErrorTracking.flush(2000);
// Close the client (disables further capturing + flushes)
await ErrorTracking.close(2000);
Enriching visitors
Attach backend context — user identity, subscription tier, custom tags — to a visitor record after they authenticate. This links the anonymous pre-login session to the known user in Analytics.
Getting the visitor ID
On apps served by Temps, the proxy stores the visitor ID in the _temps_visitor_id cookie. It is HttpOnly, so browser JavaScript can't read it and the React SDK doesn't expose it. Read it on the server instead: after login, have the frontend call one of your own API routes, and the cookie arrives with that request:
// After the user signs in
useEffect(() => {
if (user) fetch('/api/enrich-visitor', { method: 'POST' });
}, [user]);
enrichVisitor accepts the cookie value (a sealed enc_… GUID), a plain visitor GUID ("550e8400-...") or a numeric visitor ID.
Enriching from the backend
import { TempsClient } from '@temps-sdk/node-sdk';
const client = new TempsClient({
baseUrl: process.env.TEMPS_API_URL,
apiKey: process.env.TEMPS_API_KEY,
});
await client.analytics.enrichVisitor({
path: { visitor_id: visitorId },
query: { project_id: Number(process.env.TEMPS_PROJECT_ID) },
body: {
custom_data: {
userId: user.id,
email: user.email,
subscriptionTier: user.subscription?.tier ?? 'free',
signupDate: user.createdAt.toISOString(),
},
},
});
// Returns: { success: true, visitor_id: string, message: string }
Next.js API route example
// app/api/enrich-visitor/route.ts
import { cookies } from 'next/headers';
import { TempsClient } from '@temps-sdk/node-sdk';
// On Temps, TEMPS_API_URL and TEMPS_API_TOKEN (a deployment token) are injected.
// A deployment token may only enrich visitors of its own project, using the
// sealed cookie value, which is exactly what this route sends.
const client = new TempsClient({
baseUrl: process.env.TEMPS_API_URL!,
apiKey: process.env.TEMPS_API_TOKEN!,
});
export async function POST() {
const visitorId = (await cookies()).get('_temps_visitor_id')?.value;
const user = await getCurrentUser(); // your own auth/session lookup
if (!visitorId || !user) return Response.json({ success: false }, { status: 400 });
await client.analytics.enrichVisitor({
path: { visitor_id: visitorId },
query: { project_id: Number(process.env.TEMPS_PROJECT_ID) },
body: {
custom_data: {
userId: user.id,
email: user.email,
subscriptionTier: user.subscription?.tier ?? 'free',
},
},
});
return Response.json({ success: true });
}
Querying enriched visitors
// By GUID
const { data: byGuid } = await client.analytics.getVisitorByGuid({
path: { visitor_id: '550e8400-e29b-41d4-a716-446655440000' },
query: { project_id: 1 },
});
// By numeric ID
const { data: byId } = await client.analytics.getVisitorById({
path: { id: 123 },
query: { project_id: 1 },
});
console.log(byId?.custom_data);
// { userId: '123', email: 'user@example.com', subscriptionTier: 'pro' }
Feature flags
Read feature flags created in the Temps console from any service you deploy on Temps. TEMPS_API_URL and TEMPS_API_TOKEN are injected into every deployment and the token pins the project (and usually the environment), so flags.init() needs no configuration on Temps itself.
import { flags } from '@temps-sdk/node-sdk';
await flags.init();
if (flags.get('checkout.v2', { key: user.id }, false)) {
// ...
}
get() is synchronous and does zero network I/O per call: the whole environment's flag set is loaded into memory once and kept fresh by a background poll, so a per-check HTTP round trip never sits in a request handler's hot path. The third argument is the fallback — returned whenever the flag is unknown, the snapshot hasn't loaded yet, or the control plane is unreachable. flags.ready and flags.lastError are exposed so an unreachable flag service is a visible condition, not a silent one.
Locally, without TEMPS_API_URL/TEMPS_API_TOKEN set, every read returns its fallback — this is expected, not a degraded state.
Flag refresh interval
The background poll that keeps the in-memory flag snapshot fresh runs every 30 seconds by default. A flag flipped in the console reaches an already-running process on its next poll — up to 30s later, not instantly. This is deliberate: it keeps reads free of network I/O, at the cost of that window.
Override it either way:
import { FlagsClient } from '@temps-sdk/node-sdk';
const flags = new FlagsClient({ refreshIntervalMs: 5_000 });
await flags.init();
TEMPS_FLAGS_REFRESH_INTERVAL_MS is the one to reach for on a Temps deployment — set it as an environment variable on the project/environment and the default flags singleton picks it up with no redeploy of application code. A non-numeric or negative value is ignored (falls back to 30s) and logged via console.warn, rather than silently accepted.
Unchanged flags cost a 304 Not Modified, not a payload, so tightening this interval is cheap even at a low value. Setting it to 0 disables the background poll entirely — reads keep serving whatever snapshot was loaded at init().