Openstatus sdk
www.openstatus.dev
1# OpenStatus Node.js SDK (Beta)
2
3[](https://jsr.io/@openstatus/sdk-node)
4[](https://www.npmjs.com/package/@openstatus/sdk-node)
5[](https://opensource.org/licenses/MIT)
6
7Official Node.js SDK for [OpenStatus](https://openstatus.dev) - the open-source
8monitoring platform.
9
10## Features
11
12- **HTTP Monitoring** - Monitor websites and APIs with customizable assertions
13- **TCP Monitoring** - Check database connections and other TCP services
14- **DNS Monitoring** - Verify DNS records and resolution
15- **Global Regions** - Monitor from 28 locations worldwide
16- **Type-safe** - Full TypeScript support with generated types from protobuf
17
18## Installation
19
20### JSR
21
22```bash
23npx jsr add @openstatus/sdk-node
24```
25
26### npm
27
28```bash
29npm install @openstatus/sdk-node
30```
31
32### Deno
33
34```typescript
35import { openstatus } from "jsr:@openstatus/sdk-node";
36```
37
38## Quick Start
39
40```typescript
41import {
42 openstatus,
43 Periodicity,
44 Region,
45 HTTPMethod,
46 NumberComparator,
47} from "@openstatus/sdk-node";
48
49const headers = {
50 "x-openstatus-key": `${process.env.OPENSTATUS_API_KEY}`,
51};
52
53// Create a monitor
54const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor(
55 {
56 monitor: {
57 name: "My API",
58 url: "https://api.example.com/health",
59 periodicity: Periodicity.PERIODICITY_1M,
60 method: HTTPMethod.HTTP_METHOD_GET,
61 regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD],
62 active: true,
63 statusCodeAssertions: [
64 { comparator: NumberComparator.EQUAL, target: BigInt(200) },
65 ],
66 },
67 },
68 { headers },
69);
70
71console.log(`Monitor created: ${monitor?.id}`);
72
73// List all monitors
74const { httpMonitors, tcpMonitors, dnsMonitors, totalSize } =
75 await openstatus.monitor.v1.MonitorService.listMonitors({}, { headers });
76
77console.log(`Found ${totalSize} monitors`);
78```
79
80## Authentication
81
82All API requests require an API key. Get yours from the
83[OpenStatus dashboard](https://www.openstatus.dev/app).
84
85```typescript
86const headers = {
87 "x-openstatus-key": `${process.env.OPENSTATUS_API_KEY}`,
88};
89
90// Pass headers to any service method
91await openstatus.monitor.v1.MonitorService.listMonitors({}, { headers });
92```
93
94## Environment Variables
95
96| Variable | Description | Default |
97| -------------------- | ----------------------- | -------------------------------- |
98| `OPENSTATUS_API_KEY` | Your OpenStatus API key | - |
99| `OPENSTATUS_API_URL` | Custom API endpoint | `https://api.openstatus.dev/rpc` |
100
101## API Reference
102
103### Monitor Service
104
105#### `createHTTPMonitor(request, options)`
106
107Create an HTTP/HTTPS monitor.
108
109```typescript
110import { Periodicity, Region, HTTPMethod } from "@openstatus/sdk-node";
111
112const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor(
113 {
114 monitor: {
115 name: "My Website",
116 url: "https://example.com",
117 periodicity: Periodicity.PERIODICITY_1M,
118 method: HTTPMethod.HTTP_METHOD_GET,
119 regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD],
120 active: true,
121 },
122 },
123 { headers },
124);
125```
126
127#### `updateHTTPMonitor(request, options)`
128
129Update an existing HTTP monitor.
130
131```typescript
132const { monitor } = await openstatus.monitor.v1.MonitorService.updateHTTPMonitor(
133 {
134 id: "mon_123",
135 monitor: {
136 name: "Updated Name",
137 active: false,
138 },
139 },
140 { headers },
141);
142```
143
144#### `createTCPMonitor(request, options)`
145
146Create a TCP connection monitor.
147
148```typescript
149const { monitor } = await openstatus.monitor.v1.MonitorService.createTCPMonitor(
150 {
151 monitor: {
152 name: "Database",
153 uri: "db.example.com:5432",
154 periodicity: Periodicity.PERIODICITY_5M,
155 regions: [Region.FLY_AMS, Region.FLY_IAD],
156 active: true,
157 },
158 },
159 { headers },
160);
161```
162
163#### `updateTCPMonitor(request, options)`
164
165Update an existing TCP monitor.
166
167```typescript
168const { monitor } = await openstatus.monitor.v1.MonitorService.updateTCPMonitor(
169 {
170 id: "mon_123",
171 monitor: {
172 name: "Updated Database Monitor",
173 },
174 },
175 { headers },
176);
177```
178
179#### `createDNSMonitor(request, options)`
180
181Create a DNS resolution monitor.
182
183```typescript
184import { RecordComparator } from "@openstatus/sdk-node";
185
186const { monitor } = await openstatus.monitor.v1.MonitorService.createDNSMonitor(
187 {
188 monitor: {
189 name: "DNS Check",
190 uri: "example.com",
191 periodicity: Periodicity.PERIODICITY_10M,
192 regions: [Region.FLY_AMS],
193 active: true,
194 recordAssertions: [
195 {
196 record: "A",
197 comparator: RecordComparator.EQUAL,
198 target: "93.184.216.34",
199 },
200 ],
201 },
202 },
203 { headers },
204);
205```
206
207#### `updateDNSMonitor(request, options)`
208
209Update an existing DNS monitor.
210
211```typescript
212const { monitor } = await openstatus.monitor.v1.MonitorService.updateDNSMonitor(
213 {
214 id: "mon_123",
215 monitor: {
216 name: "Updated DNS Check",
217 },
218 },
219 { headers },
220);
221```
222
223#### `listMonitors(request, options)`
224
225List all monitors with pagination. Returns monitors grouped by type.
226
227```typescript
228const { httpMonitors, tcpMonitors, dnsMonitors, nextPageToken, totalSize } =
229 await openstatus.monitor.v1.MonitorService.listMonitors(
230 { pageSize: 10, pageToken: "" },
231 { headers },
232 );
233```
234
235#### `triggerMonitor(request, options)`
236
237Trigger an immediate check.
238
239```typescript
240const { success } = await openstatus.monitor.v1.MonitorService.triggerMonitor(
241 { id: "mon_123" },
242 { headers },
243);
244```
245
246#### `deleteMonitor(request, options)`
247
248Delete a monitor.
249
250```typescript
251const { success } = await openstatus.monitor.v1.MonitorService.deleteMonitor(
252 { id: "mon_123" },
253 { headers },
254);
255```
256
257#### `getMonitorStatus(request, options)`
258
259Get the current status of a monitor across all configured regions.
260
261```typescript
262import { MonitorStatus, Region } from "@openstatus/sdk-node";
263
264const { id, regions } = await openstatus.monitor.v1.MonitorService.getMonitorStatus(
265 { id: "mon_123" },
266 { headers },
267);
268
269// regions is an array of { region, status }
270// region: Region enum value (e.g., Region.FLY_AMS)
271// status: MonitorStatus.ACTIVE, MonitorStatus.DEGRADED, or MonitorStatus.ERROR
272for (const { region, status } of regions) {
273 console.log(`${Region[region]}: ${MonitorStatus[status]}`);
274}
275```
276
277#### `getMonitorSummary(request, options)`
278
279Get aggregated metrics and latency percentiles for a monitor.
280
281```typescript
282import { TimeRange } from "@openstatus/sdk-node";
283
284const summary = await openstatus.monitor.v1.MonitorService.getMonitorSummary(
285 {
286 id: "mon_123",
287 timeRange: TimeRange.TIME_RANGE_7D, // TIME_RANGE_1D, TIME_RANGE_7D, or TIME_RANGE_14D
288 regions: [], // optional: filter by specific regions
289 },
290 { headers },
291);
292
293console.log(`Last ping: ${summary.lastPingAt}`);
294console.log(`Success: ${summary.totalSuccessful}`);
295console.log(`Degraded: ${summary.totalDegraded}`);
296console.log(`Failed: ${summary.totalFailed}`);
297console.log(`P50 latency: ${summary.p50}ms`);
298console.log(`P75 latency: ${summary.p75}ms`);
299console.log(`P90 latency: ${summary.p90}ms`);
300console.log(`P95 latency: ${summary.p95}ms`);
301console.log(`P99 latency: ${summary.p99}ms`);
302```
303
304### Health Service
305
306Check API health status (no authentication required).
307
308```typescript
309import { ServingStatus } from "@openstatus/sdk-node";
310
311const { status } = await openstatus.health.v1.HealthService.check({});
312console.log(ServingStatus[status]); // "SERVING"
313```
314
315## Monitor Options
316
317### HTTP Monitor
318
319| Option | Type | Required | Description |
320| ---------------------- | ------------------ | -------- | -------------------------------------------------------- |
321| `name` | string | Yes | Monitor name (max 256 chars) |
322| `url` | string | Yes | URL to monitor (max 2048 chars) |
323| `periodicity` | Periodicity | Yes | Check interval (see [Periodicity](#periodicity)) |
324| `method` | HTTPMethod | No | HTTP method (see [HTTP Methods](#http-methods)) |
325| `body` | string | No | Request body |
326| `headers` | Headers[] | No | Custom headers (`{ key: string, value: string }[]`) |
327| `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) |
328| `retry` | bigint | No | Retry attempts (default: 3, max: 10) |
329| `followRedirects` | boolean | No | Follow redirects (default: true) |
330| `regions` | Region[] | No | [Regions](#regions) for checks |
331| `active` | boolean | No | Enable monitoring (default: false) |
332| `public` | boolean | No | Public visibility (default: false) |
333| `degradedAt` | bigint | No | Latency threshold (ms) for degraded status |
334| `description` | string | No | Monitor description (max 1024 chars) |
335| `statusCodeAssertions` | array | No | [Status code assertions](#status-code-assertions) |
336| `bodyAssertions` | array | No | [Body assertions](#body-assertions) |
337| `headerAssertions` | array | No | [Header assertions](#header-assertions) |
338| `openTelemetry` | OpenTelemetryConfig| No | OpenTelemetry export configuration |
339
340### TCP Monitor
341
342| Option | Type | Required | Description |
343| --------------- | ------------------ | -------- | ------------------------------------------------ |
344| `name` | string | Yes | Monitor name (max 256 chars) |
345| `uri` | string | Yes | `host:port` to monitor (max 2048 chars) |
346| `periodicity` | Periodicity | Yes | Check interval (see [Periodicity](#periodicity)) |
347| `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) |
348| `retry` | bigint | No | Retry attempts (default: 3, max: 10) |
349| `regions` | Region[] | No | [Regions](#regions) for checks |
350| `active` | boolean | No | Enable monitoring (default: false) |
351| `public` | boolean | No | Public visibility (default: false) |
352| `degradedAt` | bigint | No | Latency threshold (ms) for degraded status |
353| `description` | string | No | Monitor description (max 1024 chars) |
354| `openTelemetry` | OpenTelemetryConfig| No | OpenTelemetry export configuration |
355
356### DNS Monitor
357
358| Option | Type | Required | Description |
359| ------------------ | ------------------ | -------- | -------------------------------------------------- |
360| `name` | string | Yes | Monitor name (max 256 chars) |
361| `uri` | string | Yes | Domain to resolve (max 2048 chars) |
362| `periodicity` | Periodicity | Yes | Check interval (see [Periodicity](#periodicity)) |
363| `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) |
364| `retry` | bigint | No | Retry attempts (default: 3, max: 10) |
365| `regions` | Region[] | No | [Regions](#regions) for checks |
366| `active` | boolean | No | Enable monitoring (default: false) |
367| `public` | boolean | No | Public visibility (default: false) |
368| `degradedAt` | bigint | No | Latency threshold (ms) for degraded status |
369| `description` | string | No | Monitor description (max 1024 chars) |
370| `recordAssertions` | array | No | [DNS record assertions](#dns-record-assertions) |
371| `openTelemetry` | OpenTelemetryConfig| No | OpenTelemetry export configuration |
372
373### Periodicity
374
375| Enum Value | Description |
376| ----------------------- | ------------ |
377| `PERIODICITY_30S` | Every 30s |
378| `PERIODICITY_1M` | Every 1m |
379| `PERIODICITY_5M` | Every 5m |
380| `PERIODICITY_10M` | Every 10m |
381| `PERIODICITY_30M` | Every 30m |
382| `PERIODICITY_1H` | Every 1h |
383
384### HTTP Methods
385
386| Enum Value | Description |
387| ------------------------- | ----------- |
388| `HTTP_METHOD_GET` | GET |
389| `HTTP_METHOD_POST` | POST |
390| `HTTP_METHOD_HEAD` | HEAD |
391| `HTTP_METHOD_PUT` | PUT |
392| `HTTP_METHOD_PATCH` | PATCH |
393| `HTTP_METHOD_DELETE` | DELETE |
394| `HTTP_METHOD_TRACE` | TRACE |
395| `HTTP_METHOD_CONNECT` | CONNECT |
396| `HTTP_METHOD_OPTIONS` | OPTIONS |
397
398## Assertions
399
400All assertion comparators are exported as enums from the SDK.
401
402### Status Code Assertions
403
404Validate HTTP response status codes using `NumberComparator`.
405
406```typescript
407import { NumberComparator } from "@openstatus/sdk-node";
408
409{
410 statusCodeAssertions: [
411 { comparator: NumberComparator.EQUAL, target: BigInt(200) },
412 { comparator: NumberComparator.LESS_THAN, target: BigInt(400) },
413 ];
414}
415```
416
417**NumberComparator values:**
418
419| Enum Value | Description |
420| ----------------------- | ------------------------ |
421| `EQUAL` | Equal to target |
422| `NOT_EQUAL` | Not equal to target |
423| `GREATER_THAN` | Greater than target |
424| `GREATER_THAN_OR_EQUAL` | Greater than or equal |
425| `LESS_THAN` | Less than target |
426| `LESS_THAN_OR_EQUAL` | Less than or equal |
427
428### Body Assertions
429
430Validate response body content using `StringComparator`.
431
432```typescript
433import { StringComparator } from "@openstatus/sdk-node";
434
435{
436 bodyAssertions: [
437 { comparator: StringComparator.CONTAINS, target: '"status":"ok"' },
438 { comparator: StringComparator.NOT_EMPTY, target: "" },
439 ];
440}
441```
442
443**StringComparator values:**
444
445| Enum Value | Description |
446| ----------------------- | ---------------------------- |
447| `CONTAINS` | Contains target string |
448| `NOT_CONTAINS` | Does not contain target |
449| `EQUAL` | Equal to target |
450| `NOT_EQUAL` | Not equal to target |
451| `EMPTY` | Body is empty |
452| `NOT_EMPTY` | Body is not empty |
453| `GREATER_THAN` | Lexicographically greater |
454| `GREATER_THAN_OR_EQUAL` | Lexicographically >= target |
455| `LESS_THAN` | Lexicographically less |
456| `LESS_THAN_OR_EQUAL` | Lexicographically <= target |
457
458### Header Assertions
459
460Validate response headers using `StringComparator`.
461
462```typescript
463import { StringComparator } from "@openstatus/sdk-node";
464
465{
466 headerAssertions: [
467 {
468 key: "content-type",
469 comparator: StringComparator.CONTAINS,
470 target: "application/json",
471 },
472 ];
473}
474```
475
476### DNS Record Assertions
477
478Validate DNS records using `RecordComparator`.
479
480```typescript
481import { RecordComparator } from "@openstatus/sdk-node";
482
483{
484 recordAssertions: [
485 { record: "A", comparator: RecordComparator.EQUAL, target: "93.184.216.34" },
486 { record: "CNAME", comparator: RecordComparator.CONTAINS, target: "cdn" },
487 ];
488}
489```
490
491**RecordComparator values:**
492
493| Enum Value | Description |
494| -------------- | ----------------------- |
495| `EQUAL` | Equal to target |
496| `NOT_EQUAL` | Not equal to target |
497| `CONTAINS` | Contains target string |
498| `NOT_CONTAINS` | Does not contain target |
499
500**Supported record types:** `A`, `AAAA`, `CNAME`, `MX`, `TXT`
501
502## Regions
503
504Monitor from 28 global locations across multiple providers. Use the `Region` enum:
505
506```typescript
507import { Region } from "@openstatus/sdk-node";
508
509// Example: Use specific regions
510regions: [Region.FLY_AMS, Region.FLY_IAD, Region.KOYEB_FRA];
511```
512
513### Fly.io Regions
514
515| Enum Value | Location |
516| ---------- | --------------- |
517| `FLY_AMS` | Amsterdam |
518| `FLY_ARN` | Stockholm |
519| `FLY_BOM` | Mumbai |
520| `FLY_CDG` | Paris |
521| `FLY_DFW` | Dallas |
522| `FLY_EWR` | Newark |
523| `FLY_FRA` | Frankfurt |
524| `FLY_GRU` | São Paulo |
525| `FLY_IAD` | Washington D.C. |
526| `FLY_JNB` | Johannesburg |
527| `FLY_LAX` | Los Angeles |
528| `FLY_LHR` | London |
529| `FLY_NRT` | Tokyo |
530| `FLY_ORD` | Chicago |
531| `FLY_SJC` | San Jose |
532| `FLY_SIN` | Singapore |
533| `FLY_SYD` | Sydney |
534| `FLY_YYZ` | Toronto |
535
536### Koyeb Regions
537
538| Enum Value | Location |
539| ----------- | ------------- |
540| `KOYEB_FRA` | Frankfurt |
541| `KOYEB_PAR` | Paris |
542| `KOYEB_SFO` | San Francisco |
543| `KOYEB_SIN` | Singapore |
544| `KOYEB_TYO` | Tokyo |
545| `KOYEB_WAS` | Washington |
546
547### Railway Regions
548
549| Enum Value | Location |
550| ------------------------ | -------------- |
551| `RAILWAY_US_WEST2` | US West |
552| `RAILWAY_US_EAST4` | US East |
553| `RAILWAY_EUROPE_WEST4` | Europe West |
554| `RAILWAY_ASIA_SOUTHEAST1`| Asia Southeast |
555
556## Error Handling
557
558The SDK uses Connect RPC. Errors include a `code` and `message`:
559
560```typescript
561import { ConnectError } from "@connectrpc/connect";
562
563try {
564 await openstatus.monitor.v1.MonitorService.deleteMonitor(
565 { id: "invalid" },
566 { headers },
567 );
568} catch (error) {
569 if (error instanceof ConnectError) {
570 console.error(`Error ${error.code}: ${error.message}`);
571 }
572}
573```
574
575## Related
576
577- [OpenStatus](https://openstatus.dev) - Open-source monitoring platform
578- [Documentation](https://docs.openstatus.dev) - Full API documentation
579- [Status Page](https://status.openstatus.dev) - OpenStatus service status
580
581## License
582
583MIT