Node SDK

API reference for @temps-sdk/node-sdk. This package provides a typed API client for the entire Temps platform and a Sentry-compatible error tracking client for server-side Node.js applications.


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.

import { TempsClient } from '@temps-sdk/node-sdk';

const temps = new TempsClient({
  baseUrl: 'https://your-instance.temps.dev',
  apiKey: 'your-api-key',
});

// List projects
const { data: projects } = await temps.projects.list();

// Trigger a deployment
await temps.deployments.deploy({
  path: { project_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 URL (e.g. https://your-instance.temps.dev). Required.

  • Name
    apiKey
    Type
    string
    Description

    API key for authentication. Required.

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 24 typed namespaces:

NamespaceDescription
temps.apiKeysAPI key CRUD, activate/deactivate
temps.analyticsVisitors, sessions, events, enrichment, stats
temps.auditLogsAudit log retrieval
temps.authenticationLogin, logout, magic links, MFA, password reset
temps.backupsBackup schedules, S3 sources, run/restore
temps.cronsCron jobs and execution history
temps.deploymentsDeploy, cancel, pause, resume, rollback, teardown, logs
temps.dnsDNS providers, managed domains, zone listing
temps.domainsSSL/TLS domains, ACME provisioning
temps.emailEmail providers, domains, send, stats
temps.externalServicesPostgreSQL, Redis, S3 lifecycle, env vars
temps.filesFile retrieval by ID
temps.funnelsFunnel CRUD, metrics, previews
temps.gitGitHub/GitLab providers, repo connections, sync
temps.loadBalancerRoute management
temps.monitoringMonitors, incidents, uptime, status buckets
temps.notificationsPreferences, providers (email, Slack, webhook)
temps.performanceWeb Vitals metrics
temps.platformInstance info, IPs, geolocation, presets
temps.projectsFull project lifecycle: environments, domains, env vars, containers, analytics, errors, session replay, webhooks
temps.proxyLogsProxy log queries
temps.repositoriesSynced repos, branches, tags, presets
temps.sessionReplaySession init, events, deletion
temps.settingsPlatform settings
temps.usersUser 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. Initialize it once at application startup.

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 null to 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:

HandlerLevelBehavior
process.on('uncaughtException')fatalCaptured, then process.exit(1)
process.on('unhandledRejection')errorCaptured, 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');
});

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();
  • 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.

Getting the visitor ID from the frontend

import { useAnalytics } from '@temps-sdk/react-analytics';

function UserProfile({ user }) {
  const analytics = useAnalytics();

  useEffect(() => {
    const visitorId = analytics.getVisitorId();
    if (visitorId && user) {
      fetch('/api/enrich-visitor', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ visitorId, userId: user.id, email: user.email }),
      });
    }
  }, [user, analytics]);
}

The visitor ID can be a GUID string ("550e8400-...") or a numeric 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 { TempsClient } from '@temps-sdk/node-sdk';

const client = new TempsClient({
  baseUrl: process.env.TEMPS_API_URL!,
  apiKey: process.env.TEMPS_API_KEY!,
});

export async function POST(req: Request) {
  const { visitorId, userId, email } = await req.json();
  const user = await db.users.findUnique({ where: { id: userId } });

  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 visitor = await client.analytics.getVisitorByGuid({
  path: { visitor_id: '550e8400-e29b-41d4-a716-446655440000' },
  query: { project_id: 1 },
});

// By numeric ID
const visitor = await client.analytics.getVisitorById({
  path: { id: 123 },
  query: { project_id: 1 },
});

console.log(visitor.custom_data);
// { userId: '123', email: 'user@example.com', subscriptionTier: 'pro' }

Call flush() or close() before process exit to ensure all events are sent.


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().

Was this page helpful?