Official SDK for sending ingest events and uptime heartbeats to Observa.
This SDK supports both server-side and browser usage:
- Server-side (Node.js workers, backend services): initialize with
apiKey+dsnKeyfor full privileged access. - Browser / frontend: initialize with
dsnKeyonly — your org-levelapiKeystays on the server.
This SDK is an official client for the Observa backend.
You can optionally override the backend baseUrl; the SDK ensures the /v1 prefix.
- dsnKey: Project-level identifier used to route events and heartbeats. Required for all write operations.
- apiKey: Organization-level credential for privileged server-side access. Optional — omit it for browser/public usage.
npm install @observa/sdkimport { ObservaSDK } from '@observa/sdk'
const sdk = new ObservaSDK({ dsnKey: 'dsn_your_key' })The DSN is a project-scoped key safe to use in browser environments.
import { ObservaSDK } from '@observa/sdk'
const sdk = new ObservaSDK({
apiKey: 'org_api_key',
dsnKey: 'project_dsn',
baseUrl: 'https://backend-observa-production.up.railway.app',
})Use the apiKey in privileged server-side contexts (workers, backend services). Never expose your apiKey to the browser.
The SDK triggers a startup health check (/health) as a best-effort diagnostic.
This check is non-blocking: if it fails, normal SDK API calls still run with their regular timeout/retry/error behavior.
- Timeout: 5 seconds
- Retries: disabled by default
dsnKeyis requiredapiKeyis optional (server-side only)
const result = await sdk.ingest.event({
event: {
schema_version: 1,
level: 'error',
message: 'Something went wrong',
exception: {
type: 'Error',
value: 'Timeout',
stacktrace: {
frames: [{ filename: 'src/service.ts', function: 'doWork', lineno: 42, colno: 13 }],
},
},
tags: { service: 'billing' },
extra: { requestId: 'req_123' },
context: {
system: sdk.getProcessContextDynamic(),
runtime: sdk.getProcessContextStatic({ includeVersions: false }),
request: { requestId: 'req_123' },
},
},
idempotencyKey: 'req_123',
sdkVersion: '2.0.0',
})
console.log(result.event_id)Required:
dsnKeyis sent in the body asdsnKey(always)apiKeyis sent asx-api-keyheader (only when provided)
Optional:
idempotencyKeyis sent asx-idempotency-keyheader (max 128 chars)sdkVersionis sent asx-sdk-versionheader
Event context:
schema_versionidentifies the event schema version.context.systemcarries dynamic process info (pid, uptime, memory).context.runtimecarries static runtime info (node, arch, platform, release).context.requestcarries request-scoped metadata (requestId, userId, etc.).
const heartbeat = await sdk.uptime.recordHeartbeat({
status: 'up',
responseTimeMs: 120,
checkedAt: new Date().toISOString(),
message: 'Service healthy',
})
console.log(heartbeat.id)const health = await sdk.ingest.health()
console.log(health.ok)const history = await sdk.uptime.history('project_id', '2026-02-08')
const latest = await sdk.uptime.latest('project_id')
const summary = await sdk.uptime.summary('project_id', 30)These endpoints are public and do not require authentication.
sdk.setApiKey('new_api_key')The SDK throws typed errors you can catch explicitly:
import { RateLimitError, AuthError } from '@observa/sdk'
try {
await sdk.ingest.event({ event: { level: 'error', message: 'boom' } })
} catch (error) {
if (error instanceof RateLimitError) {
console.log('Retry after seconds:', error.retryAfter)
}
if (error instanceof AuthError) {
console.log('Authentication failed')
}
}- Node.js >= 18
MIT
- Documentation: ...
- GitHub: https://github.com/ObservaSolutions/sdk-observa