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
8status page with uptime monitoring.
9
10## Table of Contents
11
12- [Features](#features)
13- [Installation](#installation)
14- [Quick Start](#quick-start)
15- [Authentication](#authentication)
16- [SDK Reference](#sdk-reference)
17 - [Monitor Service](#monitor-service)
18 - [Health Service](#health-service)
19 - [Status Report Service](#status-report-service)
20 - [Status Page Service](#status-page-service)
21 - [Maintenance Service](#maintenance-service)
22 - [Notification Service](#notification-service)
23- [Reference](#reference)
24 - [Monitor Options](#monitor-options)
25 - [Assertions](#assertions)
26 - [Regions](#regions)
27 - [Enums](#enums)
28- [Error Handling](#error-handling)
29- [Related](#related)
30
31## Features
32
33### Monitoring
34
35- **HTTP Monitoring** - Monitor websites and APIs with customizable assertions
36- **TCP Monitoring** - Check database connections and other TCP services
37- **DNS Monitoring** - Verify DNS records and resolution
38- **Global Regions** - Monitor from 28 locations worldwide
39
40### Status Page
41
42- **Status Pages** - Create and manage public status pages with custom domains
43- **Page Components** - Add monitor-based or static components with grouping
44- **Subscribers** - Manage email subscriptions for status updates
45- **Status Reports** - Manage incident reports with update timelines
46- **Maintenance Windows** - Schedule and manage planned maintenance periods
47
48### Notifications
49
50- **12 Providers** - Slack, Discord, Email, PagerDuty, Opsgenie, Telegram, and
51 more
52- **Webhook Support** - Custom webhooks with headers for any integration
53- **Monitor Alerts** - Get notified when monitors go down or recover
54
55### Developer Experience
56
57- **Type-safe** - Full TypeScript support with generated types from protobuf
58- **Multiple Runtimes** - Works with Node.js, Deno, and Bun
59
60## Installation
61
62### npm
63
64```bash
65npm install @openstatus/sdk-node
66```
67
68### JSR
69
70```bash
71npx jsr add @openstatus/sdk-node
72```
73
74### Deno
75
76```typescript
77import { createOpenStatusClient } from "jsr:@openstatus/sdk-node";
78```
79
80## Quick Start
81
82```typescript
83import {
84 createOpenStatusClient,
85 HTTPMethod,
86 NumberComparator,
87 Periodicity,
88 Region,
89} from "@openstatus/sdk-node";
90
91// Create a client with your API key
92const client = createOpenStatusClient({
93 apiKey: process.env.OPENSTATUS_API_KEY,
94});
95
96// Create a monitor
97const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({
98 monitor: {
99 name: "My API",
100 url: "https://api.example.com/health",
101 periodicity: Periodicity.PERIODICITY_1M,
102 method: HTTPMethod.HTTP_METHOD_GET,
103 regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD],
104 active: true,
105 statusCodeAssertions: [
106 { comparator: NumberComparator.EQUAL, target: BigInt(200) },
107 ],
108 },
109});
110
111console.log(`Monitor created: ${monitor?.id}`);
112
113// List all monitors
114const { httpMonitors, tcpMonitors, dnsMonitors, totalSize } = await client
115 .monitor.v1.MonitorService.listMonitors({});
116
117console.log(`Found ${totalSize} monitors`);
118```
119
120## Authentication
121
122All API requests require an API key. Get yours from the
123[OpenStatus dashboard](https://www.openstatus.dev/app).
124
125### Recommended: Configure client once
126
127```typescript
128import { createOpenStatusClient } from "@openstatus/sdk-node";
129
130const client = createOpenStatusClient({
131 apiKey: process.env.OPENSTATUS_API_KEY,
132});
133
134// No need to pass headers on each call
135await client.monitor.v1.MonitorService.listMonitors({});
136```
137
138### Alternative: Manual headers
139
140```typescript
141import { openstatus } from "@openstatus/sdk-node";
142
143const headers = {
144 "x-openstatus-key": process.env.OPENSTATUS_API_KEY,
145};
146
147// Pass headers to each service method
148await openstatus.monitor.v1.MonitorService.listMonitors({}, { headers });
149```
150
151### Environment Variables
152
153| Variable | Description | Default |
154| -------------------- | ----------------------- | -------------------------------- |
155| `OPENSTATUS_API_KEY` | Your OpenStatus API key | Required |
156| `OPENSTATUS_API_URL` | Custom API endpoint | `https://api.openstatus.dev/rpc` |
157
158## SDK Reference
159
160> **Note:** All examples below assume you've created a client:
161>
162> ```typescript
163> const client = createOpenStatusClient({
164> apiKey: process.env.OPENSTATUS_API_KEY,
165> });
166> ```
167
168### Monitor Service
169
170Manage HTTP, TCP, and DNS monitors.
171
172#### `createHTTPMonitor(request)`
173
174Create an HTTP/HTTPS monitor.
175
176```typescript
177import {
178 createOpenStatusClient,
179 HTTPMethod,
180 Periodicity,
181 Region,
182} from "@openstatus/sdk-node";
183
184const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({
185 monitor: {
186 name: "My Website",
187 url: "https://example.com",
188 periodicity: Periodicity.PERIODICITY_1M,
189 method: HTTPMethod.HTTP_METHOD_GET,
190 regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD],
191 active: true,
192 },
193});
194```
195
196#### `updateHTTPMonitor(request)`
197
198Update an existing HTTP monitor.
199
200```typescript
201const { monitor } = await client.monitor.v1.MonitorService.updateHTTPMonitor({
202 id: "mon_123",
203 monitor: {
204 name: "Updated Name",
205 active: false,
206 },
207});
208```
209
210#### `createTCPMonitor(request)`
211
212Create a TCP connection monitor.
213
214```typescript
215const { monitor } = await client.monitor.v1.MonitorService.createTCPMonitor({
216 monitor: {
217 name: "Database",
218 uri: "db.example.com:5432",
219 periodicity: Periodicity.PERIODICITY_5M,
220 regions: [Region.FLY_AMS, Region.FLY_IAD],
221 active: true,
222 },
223});
224```
225
226#### `updateTCPMonitor(request)`
227
228Update an existing TCP monitor.
229
230```typescript
231const { monitor } = await client.monitor.v1.MonitorService.updateTCPMonitor({
232 id: "mon_123",
233 monitor: {
234 name: "Updated Database Monitor",
235 },
236});
237```
238
239#### `createDNSMonitor(request)`
240
241Create a DNS resolution monitor.
242
243```typescript
244import { Periodicity, RecordComparator, Region } from "@openstatus/sdk-node";
245
246const { monitor } = await client.monitor.v1.MonitorService.createDNSMonitor({
247 monitor: {
248 name: "DNS Check",
249 uri: "example.com",
250 periodicity: Periodicity.PERIODICITY_10M,
251 regions: [Region.FLY_AMS],
252 active: true,
253 recordAssertions: [
254 {
255 record: "A",
256 comparator: RecordComparator.EQUAL,
257 target: "93.184.216.34",
258 },
259 ],
260 },
261});
262```
263
264#### `updateDNSMonitor(request)`
265
266Update an existing DNS monitor.
267
268```typescript
269const { monitor } = await client.monitor.v1.MonitorService.updateDNSMonitor({
270 id: "mon_123",
271 monitor: {
272 name: "Updated DNS Check",
273 },
274});
275```
276
277#### `listMonitors(request)`
278
279List all monitors with pagination. Returns monitors grouped by type.
280
281```typescript
282const { httpMonitors, tcpMonitors, dnsMonitors, nextPageToken, totalSize } =
283 await client.monitor.v1.MonitorService.listMonitors({
284 pageSize: 10,
285 pageToken: "",
286 });
287```
288
289#### `triggerMonitor(request)`
290
291Trigger an immediate check.
292
293```typescript
294const { success } = await client.monitor.v1.MonitorService.triggerMonitor({
295 id: "mon_123",
296});
297```
298
299#### `deleteMonitor(request)`
300
301Delete a monitor.
302
303```typescript
304const { success } = await client.monitor.v1.MonitorService.deleteMonitor({
305 id: "mon_123",
306});
307```
308
309#### `getMonitorStatus(request)`
310
311Get the current status of a monitor across all configured regions.
312
313```typescript
314import { MonitorStatus, Region } from "@openstatus/sdk-node";
315
316const { id, regions } = await client.monitor.v1.MonitorService.getMonitorStatus(
317 { id: "mon_123" },
318);
319
320for (const { region, status } of regions) {
321 console.log(`${Region[region]}: ${MonitorStatus[status]}`);
322}
323```
324
325#### `getMonitorSummary(request)`
326
327Get aggregated metrics and latency percentiles for a monitor.
328
329```typescript
330import { TimeRange } from "@openstatus/sdk-node";
331
332const summary = await client.monitor.v1.MonitorService.getMonitorSummary({
333 id: "mon_123",
334 timeRange: TimeRange.TIME_RANGE_7D,
335 regions: [], // optional: filter by specific regions
336});
337
338console.log(`Last ping: ${summary.lastPingAt}`);
339console.log(`Success: ${summary.totalSuccessful}`);
340console.log(`Failed: ${summary.totalFailed}`);
341console.log(`P50 latency: ${summary.p50}ms`);
342console.log(`P95 latency: ${summary.p95}ms`);
343console.log(`P99 latency: ${summary.p99}ms`);
344```
345
346---
347
348### Health Service
349
350Check API health status (no authentication required).
351
352```typescript
353import { openstatus, ServingStatus } from "@openstatus/sdk-node";
354
355const { status } = await openstatus.health.v1.HealthService.check({});
356console.log(ServingStatus[status]); // "SERVING"
357```
358
359---
360
361### Status Report Service
362
363Manage incident reports with update timelines.
364
365#### `createStatusReport(request)`
366
367Create a new status report.
368
369```typescript
370import { StatusReportStatus } from "@openstatus/sdk-node";
371
372const { statusReport } = await client.statusReport.v1.StatusReportService
373 .createStatusReport({
374 title: "API Degradation",
375 status: StatusReportStatus.INVESTIGATING,
376 message: "We are investigating reports of increased latency.",
377 date: "2024-01-15T10:30:00Z",
378 pageId: "page_123",
379 pageComponentIds: ["comp_456"],
380 notify: true,
381 });
382
383console.log(`Status report created: ${statusReport?.id}`);
384```
385
386#### `getStatusReport(request)`
387
388Get a status report by ID (includes full update timeline).
389
390```typescript
391import { StatusReportStatus } from "@openstatus/sdk-node";
392
393const { statusReport } = await client.statusReport.v1.StatusReportService
394 .getStatusReport({
395 id: "sr_123",
396 });
397
398console.log(`Title: ${statusReport?.title}`);
399console.log(`Status: ${StatusReportStatus[statusReport?.status ?? 0]}`);
400
401for (const update of statusReport?.updates ?? []) {
402 console.log(`${update.date}: ${update.message}`);
403}
404```
405
406#### `listStatusReports(request)`
407
408List all status reports with pagination and optional filtering.
409
410```typescript
411import { StatusReportStatus } from "@openstatus/sdk-node";
412
413const { statusReports, totalSize } = await client.statusReport.v1
414 .StatusReportService.listStatusReports({
415 limit: 10,
416 offset: 0,
417 statuses: [StatusReportStatus.INVESTIGATING, StatusReportStatus.IDENTIFIED],
418 });
419
420console.log(`Found ${totalSize} status reports`);
421```
422
423#### `updateStatusReport(request)`
424
425Update status report metadata.
426
427```typescript
428const { statusReport } = await client.statusReport.v1.StatusReportService
429 .updateStatusReport({
430 id: "sr_123",
431 title: "Updated Title",
432 pageComponentIds: ["comp_456", "comp_789"],
433 });
434```
435
436#### `deleteStatusReport(request)`
437
438Delete a status report and all its updates.
439
440```typescript
441const { success } = await client.statusReport.v1.StatusReportService
442 .deleteStatusReport({
443 id: "sr_123",
444 });
445```
446
447#### `addStatusReportUpdate(request)`
448
449Add a new update to an existing status report timeline.
450
451```typescript
452import { StatusReportStatus } from "@openstatus/sdk-node";
453
454const { statusReport } = await client.statusReport.v1.StatusReportService
455 .addStatusReportUpdate({
456 statusReportId: "sr_123",
457 status: StatusReportStatus.IDENTIFIED,
458 message: "The issue has been identified as a database connection problem.",
459 date: "2024-01-15T11:00:00Z", // optional, defaults to current time
460 notify: true,
461 });
462```
463
464---
465
466### Status Page Service
467
468Manage status pages, components, and subscribers.
469
470#### `createStatusPage(request)`
471
472Create a new status page.
473
474```typescript
475const { statusPage } = await client.statusPage.v1.StatusPageService
476 .createStatusPage({
477 title: "My Service Status",
478 slug: "my-service",
479 description: "Status page for My Service",
480 homepageUrl: "https://example.com",
481 contactUrl: "https://example.com/contact",
482 });
483
484console.log(`Status page created: ${statusPage?.id}`);
485```
486
487#### `getStatusPage(request)`
488
489Get a status page by ID.
490
491```typescript
492const { statusPage } = await client.statusPage.v1.StatusPageService
493 .getStatusPage({
494 id: "page_123",
495 });
496```
497
498#### `listStatusPages(request)`
499
500List all status pages with pagination.
501
502```typescript
503const { statusPages, totalSize } = await client.statusPage.v1.StatusPageService
504 .listStatusPages({ limit: 10, offset: 0 });
505
506console.log(`Found ${totalSize} status pages`);
507```
508
509#### `updateStatusPage(request)`
510
511Update a status page.
512
513```typescript
514const { statusPage } = await client.statusPage.v1.StatusPageService
515 .updateStatusPage({
516 id: "page_123",
517 title: "Updated Title",
518 description: "Updated description",
519 });
520```
521
522#### `deleteStatusPage(request)`
523
524Delete a status page.
525
526```typescript
527const { success } = await client.statusPage.v1.StatusPageService
528 .deleteStatusPage({
529 id: "page_123",
530 });
531```
532
533#### `addMonitorComponent(request)`
534
535Add a monitor-based component to a status page.
536
537```typescript
538const { component } = await client.statusPage.v1.StatusPageService
539 .addMonitorComponent({
540 pageId: "page_123",
541 monitorId: "mon_456",
542 name: "API Server",
543 description: "Main API endpoint",
544 order: 1,
545 });
546```
547
548#### `addStaticComponent(request)`
549
550Add a static component (not linked to a monitor).
551
552```typescript
553const { component } = await client.statusPage.v1.StatusPageService
554 .addStaticComponent({
555 pageId: "page_123",
556 name: "Third-party Service",
557 description: "External dependency",
558 order: 2,
559 });
560```
561
562#### `updateComponent(request)`
563
564Update a component.
565
566```typescript
567const { component } = await client.statusPage.v1.StatusPageService
568 .updateComponent({
569 id: "comp_123",
570 name: "Updated Component Name",
571 order: 3,
572 });
573```
574
575#### `removeComponent(request)`
576
577Remove a component from a status page.
578
579```typescript
580const { success } = await client.statusPage.v1.StatusPageService
581 .removeComponent({
582 id: "comp_123",
583 });
584```
585
586#### `createComponentGroup(request)`
587
588Create a component group.
589
590```typescript
591const { group } = await client.statusPage.v1.StatusPageService
592 .createComponentGroup({
593 pageId: "page_123",
594 name: "Core Services",
595 });
596```
597
598#### `updateComponentGroup(request)`
599
600Update a component group.
601
602```typescript
603const { group } = await client.statusPage.v1.StatusPageService
604 .updateComponentGroup({
605 id: "group_123",
606 name: "Updated Group Name",
607 });
608```
609
610#### `deleteComponentGroup(request)`
611
612Delete a component group.
613
614```typescript
615const { success } = await client.statusPage.v1.StatusPageService
616 .deleteComponentGroup({
617 id: "group_123",
618 });
619```
620
621#### `subscribeToPage(request)`
622
623Subscribe an email to status page updates.
624
625```typescript
626const { subscriber } = await client.statusPage.v1.StatusPageService
627 .subscribeToPage({
628 pageId: "page_123",
629 email: "user@example.com",
630 });
631```
632
633#### `unsubscribeFromPage(request)`
634
635Unsubscribe from a status page.
636
637```typescript
638// By email
639const { success } = await client.statusPage.v1.StatusPageService
640 .unsubscribeFromPage({
641 pageId: "page_123",
642 identifier: { case: "email", value: "user@example.com" },
643 });
644
645// Or by subscriber ID
646const { success: success2 } = await client.statusPage.v1.StatusPageService
647 .unsubscribeFromPage({
648 pageId: "page_123",
649 identifier: { case: "id", value: "sub_456" },
650 });
651```
652
653#### `listSubscribers(request)`
654
655List all subscribers for a status page.
656
657```typescript
658const { subscribers, totalSize } = await client.statusPage.v1.StatusPageService
659 .listSubscribers({
660 pageId: "page_123",
661 limit: 50,
662 offset: 0,
663 includeUnsubscribed: false,
664 });
665```
666
667#### `getStatusPageContent(request)`
668
669Get full status page content including components, groups, and active reports.
670
671```typescript
672const content = await client.statusPage.v1.StatusPageService
673 .getStatusPageContent({
674 identifier: { case: "slug", value: "my-service" },
675 });
676
677console.log(`Page: ${content.statusPage?.title}`);
678console.log(`Components: ${content.components.length}`);
679console.log(`Active reports: ${content.statusReports.length}`);
680```
681
682#### `getOverallStatus(request)`
683
684Get the aggregated status of a status page.
685
686```typescript
687import { OverallStatus } from "@openstatus/sdk-node";
688
689const { overallStatus, componentStatuses } = await client.statusPage.v1
690 .StatusPageService.getOverallStatus({
691 identifier: { case: "id", value: "page_123" },
692 });
693
694console.log(`Overall: ${OverallStatus[overallStatus]}`);
695for (const { componentId, status } of componentStatuses) {
696 console.log(` ${componentId}: ${OverallStatus[status]}`);
697}
698```
699
700---
701
702### Maintenance Service
703
704Manage scheduled maintenance windows.
705
706#### `createMaintenance(request)`
707
708Create a new maintenance window.
709
710```typescript
711const { maintenance } = await client.maintenance.v1.MaintenanceService
712 .createMaintenance({
713 title: "Database Upgrade",
714 message: "We will be upgrading our database infrastructure.",
715 from: "2024-01-20T02:00:00Z",
716 to: "2024-01-20T04:00:00Z",
717 pageId: "page_123",
718 pageComponentIds: ["comp_456"],
719 notify: true,
720 });
721
722console.log(`Maintenance created: ${maintenance?.id}`);
723```
724
725#### `getMaintenance(request)`
726
727Get a maintenance window by ID.
728
729```typescript
730const { maintenance } = await client.maintenance.v1.MaintenanceService
731 .getMaintenance({
732 id: "maint_123",
733 });
734
735console.log(`Title: ${maintenance?.title}`);
736console.log(`From: ${maintenance?.from}`);
737console.log(`To: ${maintenance?.to}`);
738```
739
740#### `listMaintenances(request)`
741
742List all maintenance windows with pagination and optional filtering.
743
744```typescript
745const { maintenances, totalSize } = await client.maintenance.v1
746 .MaintenanceService.listMaintenances({
747 limit: 10,
748 offset: 0,
749 pageId: "page_123", // optional filter
750 });
751
752console.log(`Found ${totalSize} maintenance windows`);
753```
754
755#### `updateMaintenance(request)`
756
757Update a maintenance window.
758
759```typescript
760const { maintenance } = await client.maintenance.v1.MaintenanceService
761 .updateMaintenance({
762 id: "maint_123",
763 title: "Extended Database Upgrade",
764 to: "2024-01-20T06:00:00Z",
765 });
766```
767
768#### `deleteMaintenance(request)`
769
770Delete a maintenance window.
771
772```typescript
773const { success } = await client.maintenance.v1.MaintenanceService
774 .deleteMaintenance({
775 id: "maint_123",
776 });
777```
778
779---
780
781### Notification Service
782
783Manage notification channels for monitor alerts. Supports 12 providers including
784Slack, Discord, Email, PagerDuty, and custom webhooks.
785
786#### `createNotification(request)`
787
788Create a new notification channel.
789
790```typescript
791import { NotificationProvider } from "@openstatus/sdk-node";
792
793const { notification } = await client.notification.v1.NotificationService
794 .createNotification({
795 name: "Slack Alerts",
796 provider: NotificationProvider.SLACK,
797 data: {
798 data: {
799 case: "slack",
800 value: { webhookUrl: "https://hooks.slack.com/services/..." },
801 },
802 },
803 monitorIds: ["mon_123", "mon_456"],
804 });
805
806console.log(`Notification created: ${notification?.id}`);
807```
808
809#### `getNotification(request)`
810
811Get a notification channel by ID.
812
813```typescript
814import { NotificationProvider } from "@openstatus/sdk-node";
815
816const { notification } = await client.notification.v1.NotificationService
817 .getNotification({
818 id: "notif_123",
819 });
820
821console.log(`Name: ${notification?.name}`);
822console.log(`Provider: ${NotificationProvider[notification?.provider ?? 0]}`);
823```
824
825#### `listNotifications(request)`
826
827List all notification channels with pagination.
828
829```typescript
830const { notifications, totalSize } = await client.notification.v1
831 .NotificationService.listNotifications({ limit: 10, offset: 0 });
832
833console.log(`Found ${totalSize} notification channels`);
834```
835
836#### `updateNotification(request)`
837
838Update a notification channel.
839
840```typescript
841const { notification } = await client.notification.v1.NotificationService
842 .updateNotification({
843 id: "notif_123",
844 name: "Updated Slack Alerts",
845 monitorIds: ["mon_123", "mon_456", "mon_789"],
846 });
847```
848
849#### `deleteNotification(request)`
850
851Delete a notification channel.
852
853```typescript
854const { success } = await client.notification.v1.NotificationService
855 .deleteNotification({
856 id: "notif_123",
857 });
858```
859
860#### `sendTestNotification(request)`
861
862Send a test notification to verify configuration.
863
864```typescript
865import { NotificationProvider } from "@openstatus/sdk-node";
866
867const { success, errorMessage } = await client.notification.v1
868 .NotificationService.sendTestNotification({
869 provider: NotificationProvider.SLACK,
870 data: {
871 data: {
872 case: "slack",
873 value: { webhookUrl: "https://hooks.slack.com/services/..." },
874 },
875 },
876 });
877
878if (success) {
879 console.log("Test notification sent successfully");
880} else {
881 console.log(`Test failed: ${errorMessage}`);
882}
883```
884
885#### `checkNotificationLimit(request)`
886
887Check if the workspace has reached its notification limit.
888
889```typescript
890const { limitReached, currentCount, maxCount } = await client.notification.v1
891 .NotificationService.checkNotificationLimit({});
892
893console.log(`${currentCount}/${maxCount} notification channels used`);
894```
895
896#### Provider Configuration Examples
897
898<details>
899<summary><strong>Slack</strong></summary>
900
901```typescript
902{
903 provider: NotificationProvider.SLACK,
904 data: {
905 data: {
906 case: "slack",
907 value: { webhookUrl: "https://hooks.slack.com/services/..." }
908 }
909 }
910}
911```
912
913</details>
914
915<details>
916<summary><strong>Discord</strong></summary>
917
918```typescript
919{
920 provider: NotificationProvider.DISCORD,
921 data: {
922 data: {
923 case: "discord",
924 value: { webhookUrl: "https://discord.com/api/webhooks/..." }
925 }
926 }
927}
928```
929
930</details>
931
932<details>
933<summary><strong>Email</strong></summary>
934
935```typescript
936{
937 provider: NotificationProvider.EMAIL,
938 data: {
939 data: {
940 case: "email",
941 value: { email: "alerts@example.com" }
942 }
943 }
944}
945```
946
947</details>
948
949<details>
950<summary><strong>PagerDuty</strong></summary>
951
952```typescript
953{
954 provider: NotificationProvider.PAGERDUTY,
955 data: {
956 data: {
957 case: "pagerduty",
958 value: { integrationKey: "your-integration-key" }
959 }
960 }
961}
962```
963
964</details>
965
966<details>
967<summary><strong>Opsgenie</strong></summary>
968
969```typescript
970import { OpsgenieRegion } from "@openstatus/sdk-node";
971
972{
973 provider: NotificationProvider.OPSGENIE,
974 data: {
975 data: {
976 case: "opsgenie",
977 value: { apiKey: "your-api-key", region: OpsgenieRegion.US }
978 }
979 }
980}
981```
982
983</details>
984
985<details>
986<summary><strong>Telegram</strong></summary>
987
988```typescript
989{
990 provider: NotificationProvider.TELEGRAM,
991 data: {
992 data: {
993 case: "telegram",
994 value: { chatId: "123456789" }
995 }
996 }
997}
998```
999
1000</details>
1001
1002<details>
1003<summary><strong>Google Chat</strong></summary>
1004
1005```typescript
1006{
1007 provider: NotificationProvider.GOOGLE_CHAT,
1008 data: {
1009 data: {
1010 case: "googleChat",
1011 value: { webhookUrl: "https://chat.googleapis.com/v1/spaces/..." }
1012 }
1013 }
1014}
1015```
1016
1017</details>
1018
1019<details>
1020<summary><strong>Grafana OnCall</strong></summary>
1021
1022```typescript
1023{
1024 provider: NotificationProvider.GRAFANA_ONCALL,
1025 data: {
1026 data: {
1027 case: "grafanaOncall",
1028 value: { webhookUrl: "https://oncall.example.com/..." }
1029 }
1030 }
1031}
1032```
1033
1034</details>
1035
1036<details>
1037<summary><strong>Ntfy</strong></summary>
1038
1039```typescript
1040{
1041 provider: NotificationProvider.NTFY,
1042 data: {
1043 data: {
1044 case: "ntfy",
1045 value: {
1046 topic: "my-alerts",
1047 serverUrl: "https://ntfy.sh", // optional, defaults to ntfy.sh
1048 token: "tk_..." // optional auth token
1049 }
1050 }
1051 }
1052}
1053```
1054
1055</details>
1056
1057<details>
1058<summary><strong>SMS</strong></summary>
1059
1060```typescript
1061{
1062 provider: NotificationProvider.SMS,
1063 data: {
1064 data: {
1065 case: "sms",
1066 value: { phoneNumber: "+1234567890" }
1067 }
1068 }
1069}
1070```
1071
1072</details>
1073
1074<details>
1075<summary><strong>WhatsApp</strong></summary>
1076
1077```typescript
1078{
1079 provider: NotificationProvider.WHATSAPP,
1080 data: {
1081 data: {
1082 case: "whatsapp",
1083 value: { phoneNumber: "+1234567890" }
1084 }
1085 }
1086}
1087```
1088
1089</details>
1090
1091<details>
1092<summary><strong>Custom Webhook</strong></summary>
1093
1094```typescript
1095{
1096 provider: NotificationProvider.WEBHOOK,
1097 data: {
1098 data: {
1099 case: "webhook",
1100 value: {
1101 endpoint: "https://api.example.com/webhook",
1102 headers: [
1103 { key: "Authorization", value: "Bearer token" },
1104 { key: "X-Custom-Header", value: "value" }
1105 ]
1106 }
1107 }
1108 }
1109}
1110```
1111
1112</details>
1113
1114---
1115
1116## Reference
1117
1118### Monitor Options
1119
1120#### HTTP Monitor
1121
1122| Option | Type | Required | Description |
1123| ---------------------- | ------------------- | -------- | ------------------------------------------- |
1124| `name` | string | Yes | Monitor name (max 256 chars) |
1125| `url` | string | Yes | URL to monitor (max 2048 chars) |
1126| `periodicity` | Periodicity | Yes | Check interval |
1127| `method` | HTTPMethod | No | HTTP method (default: GET) |
1128| `body` | string | No | Request body |
1129| `headers` | Headers[] | No | Custom headers `{ key, value }[]` |
1130| `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) |
1131| `retry` | bigint | No | Retry attempts (default: 3, max: 10) |
1132| `followRedirects` | boolean | No | Follow redirects (default: true) |
1133| `regions` | Region[] | No | Regions for checks |
1134| `active` | boolean | No | Enable monitoring (default: false) |
1135| `public` | boolean | No | Public visibility (default: false) |
1136| `degradedAt` | bigint | No | Latency threshold (ms) for degraded status |
1137| `description` | string | No | Monitor description (max 1024 chars) |
1138| `statusCodeAssertions` | array | No | Status code assertions |
1139| `bodyAssertions` | array | No | Body assertions |
1140| `headerAssertions` | array | No | Header assertions |
1141| `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration |
1142
1143#### TCP Monitor
1144
1145| Option | Type | Required | Description |
1146| --------------- | ------------------- | -------- | ------------------------------------------- |
1147| `name` | string | Yes | Monitor name (max 256 chars) |
1148| `uri` | string | Yes | `host:port` to monitor (max 2048 chars) |
1149| `periodicity` | Periodicity | Yes | Check interval |
1150| `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) |
1151| `retry` | bigint | No | Retry attempts (default: 3, max: 10) |
1152| `regions` | Region[] | No | Regions for checks |
1153| `active` | boolean | No | Enable monitoring (default: false) |
1154| `public` | boolean | No | Public visibility (default: false) |
1155| `degradedAt` | bigint | No | Latency threshold (ms) for degraded status |
1156| `description` | string | No | Monitor description (max 1024 chars) |
1157| `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration |
1158
1159#### DNS Monitor
1160
1161| Option | Type | Required | Description |
1162| ------------------ | ------------------- | -------- | ------------------------------------------- |
1163| `name` | string | Yes | Monitor name (max 256 chars) |
1164| `uri` | string | Yes | Domain to resolve (max 2048 chars) |
1165| `periodicity` | Periodicity | Yes | Check interval |
1166| `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) |
1167| `retry` | bigint | No | Retry attempts (default: 3, max: 10) |
1168| `regions` | Region[] | No | Regions for checks |
1169| `active` | boolean | No | Enable monitoring (default: false) |
1170| `public` | boolean | No | Public visibility (default: false) |
1171| `degradedAt` | bigint | No | Latency threshold (ms) for degraded status |
1172| `description` | string | No | Monitor description (max 1024 chars) |
1173| `recordAssertions` | array | No | DNS record assertions |
1174| `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration |
1175
1176---
1177
1178### Assertions
1179
1180#### Status Code Assertions
1181
1182Validate HTTP response status codes using `NumberComparator`.
1183
1184```typescript
1185import { NumberComparator } from "@openstatus/sdk-node";
1186
1187{
1188 statusCodeAssertions: [
1189 { comparator: NumberComparator.EQUAL, target: BigInt(200) },
1190 { comparator: NumberComparator.LESS_THAN, target: BigInt(400) },
1191 ];
1192}
1193```
1194
1195#### Body Assertions
1196
1197Validate response body content using `StringComparator`.
1198
1199```typescript
1200import { StringComparator } from "@openstatus/sdk-node";
1201
1202{
1203 bodyAssertions: [
1204 { comparator: StringComparator.CONTAINS, target: '"status":"ok"' },
1205 { comparator: StringComparator.NOT_EMPTY, target: "" },
1206 ];
1207}
1208```
1209
1210#### Header Assertions
1211
1212Validate response headers using `StringComparator`.
1213
1214```typescript
1215import { StringComparator } from "@openstatus/sdk-node";
1216
1217{
1218 headerAssertions: [
1219 {
1220 key: "content-type",
1221 comparator: StringComparator.CONTAINS,
1222 target: "application/json",
1223 },
1224 ];
1225}
1226```
1227
1228#### DNS Record Assertions
1229
1230Validate DNS records using `RecordComparator`.
1231
1232```typescript
1233import { RecordComparator } from "@openstatus/sdk-node";
1234
1235{
1236 recordAssertions: [
1237 {
1238 record: "A",
1239 comparator: RecordComparator.EQUAL,
1240 target: "93.184.216.34",
1241 },
1242 { record: "CNAME", comparator: RecordComparator.CONTAINS, target: "cdn" },
1243 ];
1244}
1245```
1246
1247**Supported record types:** `A`, `AAAA`, `CNAME`, `MX`, `TXT`
1248
1249---
1250
1251### Regions
1252
1253Monitor from 28 global locations across multiple providers.
1254
1255```typescript
1256import { Region } from "@openstatus/sdk-node";
1257
1258regions: [Region.FLY_AMS, Region.FLY_IAD, Region.KOYEB_FRA];
1259```
1260
1261#### Fly.io Regions (18)
1262
1263| Enum Value | Location |
1264| ---------- | --------------- |
1265| `FLY_AMS` | Amsterdam |
1266| `FLY_ARN` | Stockholm |
1267| `FLY_BOM` | Mumbai |
1268| `FLY_CDG` | Paris |
1269| `FLY_DFW` | Dallas |
1270| `FLY_EWR` | Newark |
1271| `FLY_FRA` | Frankfurt |
1272| `FLY_GRU` | São Paulo |
1273| `FLY_IAD` | Washington D.C. |
1274| `FLY_JNB` | Johannesburg |
1275| `FLY_LAX` | Los Angeles |
1276| `FLY_LHR` | London |
1277| `FLY_NRT` | Tokyo |
1278| `FLY_ORD` | Chicago |
1279| `FLY_SJC` | San Jose |
1280| `FLY_SIN` | Singapore |
1281| `FLY_SYD` | Sydney |
1282| `FLY_YYZ` | Toronto |
1283
1284#### Koyeb Regions (6)
1285
1286| Enum Value | Location |
1287| ----------- | ------------- |
1288| `KOYEB_FRA` | Frankfurt |
1289| `KOYEB_PAR` | Paris |
1290| `KOYEB_SFO` | San Francisco |
1291| `KOYEB_SIN` | Singapore |
1292| `KOYEB_TYO` | Tokyo |
1293| `KOYEB_WAS` | Washington |
1294
1295#### Railway Regions (4)
1296
1297| Enum Value | Location |
1298| ------------------------- | -------------- |
1299| `RAILWAY_US_WEST2` | US West |
1300| `RAILWAY_US_EAST4` | US East |
1301| `RAILWAY_EUROPE_WEST4` | Europe West |
1302| `RAILWAY_ASIA_SOUTHEAST1` | Asia Southeast |
1303
1304---
1305
1306### Enums
1307
1308#### Periodicity
1309
1310| Value | Description |
1311| ----------------- | ----------- |
1312| `PERIODICITY_30S` | Every 30s |
1313| `PERIODICITY_1M` | Every 1m |
1314| `PERIODICITY_5M` | Every 5m |
1315| `PERIODICITY_10M` | Every 10m |
1316| `PERIODICITY_30M` | Every 30m |
1317| `PERIODICITY_1H` | Every 1h |
1318
1319#### HTTPMethod
1320
1321| Value | Description |
1322| --------------------- | ----------- |
1323| `HTTP_METHOD_GET` | GET |
1324| `HTTP_METHOD_POST` | POST |
1325| `HTTP_METHOD_HEAD` | HEAD |
1326| `HTTP_METHOD_PUT` | PUT |
1327| `HTTP_METHOD_PATCH` | PATCH |
1328| `HTTP_METHOD_DELETE` | DELETE |
1329| `HTTP_METHOD_TRACE` | TRACE |
1330| `HTTP_METHOD_CONNECT` | CONNECT |
1331| `HTTP_METHOD_OPTIONS` | OPTIONS |
1332
1333#### MonitorStatus
1334
1335| Value | Description |
1336| ---------- | -------------------------- |
1337| `ACTIVE` | Monitor is healthy |
1338| `DEGRADED` | Latency threshold exceeded |
1339| `ERROR` | Monitor is failing |
1340
1341#### TimeRange
1342
1343| Value | Description |
1344| ---------------- | ------------ |
1345| `TIME_RANGE_1D` | Last 1 day |
1346| `TIME_RANGE_7D` | Last 7 days |
1347| `TIME_RANGE_14D` | Last 14 days |
1348
1349#### StatusReportStatus
1350
1351| Value | Description |
1352| --------------- | -------------------------------- |
1353| `INVESTIGATING` | Actively investigating the issue |
1354| `IDENTIFIED` | Root cause has been identified |
1355| `MONITORING` | Fix deployed, monitoring |
1356| `RESOLVED` | Issue fully resolved |
1357
1358#### OverallStatus
1359
1360| Value | Description |
1361| ---------------- | --------------------------- |
1362| `OPERATIONAL` | All systems operational |
1363| `DEGRADED` | Performance is degraded |
1364| `PARTIAL_OUTAGE` | Some systems are down |
1365| `MAJOR_OUTAGE` | Major systems are down |
1366| `MAINTENANCE` | Scheduled maintenance |
1367| `UNKNOWN` | Status cannot be determined |
1368
1369#### NotificationProvider
1370
1371| Value | Description |
1372| ---------------- | ------------------- |
1373| `DISCORD` | Discord webhook |
1374| `EMAIL` | Email notification |
1375| `GOOGLE_CHAT` | Google Chat webhook |
1376| `GRAFANA_ONCALL` | Grafana OnCall |
1377| `NTFY` | Ntfy push service |
1378| `PAGERDUTY` | PagerDuty |
1379| `OPSGENIE` | Opsgenie |
1380| `SLACK` | Slack webhook |
1381| `SMS` | SMS notification |
1382| `TELEGRAM` | Telegram bot |
1383| `WEBHOOK` | Custom webhook |
1384| `WHATSAPP` | WhatsApp |
1385
1386#### OpsgenieRegion
1387
1388| Value | Description |
1389| ----- | ----------- |
1390| `US` | US region |
1391| `EU` | EU region |
1392
1393#### PageAccessType
1394
1395| Value | Description |
1396| -------------------- | ----------------------- |
1397| `PUBLIC` | Publicly accessible |
1398| `PASSWORD_PROTECTED` | Requires password |
1399| `AUTHENTICATED` | Requires authentication |
1400
1401#### PageTheme
1402
1403| Value | Description |
1404| -------- | ------------------- |
1405| `SYSTEM` | Follow system theme |
1406| `LIGHT` | Light theme |
1407| `DARK` | Dark theme |
1408
1409#### PageComponentType
1410
1411| Value | Description |
1412| --------- | ------------------------- |
1413| `MONITOR` | Linked to a monitor |
1414| `STATIC` | Static component (manual) |
1415
1416#### NumberComparator
1417
1418| Value | Description |
1419| ----------------------- | --------------------- |
1420| `EQUAL` | Equal to target |
1421| `NOT_EQUAL` | Not equal to target |
1422| `GREATER_THAN` | Greater than target |
1423| `GREATER_THAN_OR_EQUAL` | Greater than or equal |
1424| `LESS_THAN` | Less than target |
1425| `LESS_THAN_OR_EQUAL` | Less than or equal |
1426
1427#### StringComparator
1428
1429| Value | Description |
1430| ----------------------- | --------------------------- |
1431| `CONTAINS` | Contains target string |
1432| `NOT_CONTAINS` | Does not contain target |
1433| `EQUAL` | Equal to target |
1434| `NOT_EQUAL` | Not equal to target |
1435| `EMPTY` | Value is empty |
1436| `NOT_EMPTY` | Value is not empty |
1437| `GREATER_THAN` | Lexicographically greater |
1438| `GREATER_THAN_OR_EQUAL` | Lexicographically >= target |
1439| `LESS_THAN` | Lexicographically less |
1440| `LESS_THAN_OR_EQUAL` | Lexicographically <= target |
1441
1442#### RecordComparator
1443
1444| Value | Description |
1445| -------------- | ----------------------- |
1446| `EQUAL` | Equal to target |
1447| `NOT_EQUAL` | Not equal to target |
1448| `CONTAINS` | Contains target string |
1449| `NOT_CONTAINS` | Does not contain target |
1450
1451---
1452
1453## Error Handling
1454
1455The SDK uses Connect RPC. Errors include a `code` and `message`:
1456
1457```typescript
1458import { ConnectError } from "@connectrpc/connect";
1459
1460try {
1461 await client.monitor.v1.MonitorService.deleteMonitor({ id: "invalid" });
1462} catch (error) {
1463 if (error instanceof ConnectError) {
1464 console.error(`Error ${error.code}: ${error.message}`);
1465 }
1466}
1467```
1468
1469## Related
1470
1471- [OpenStatus](https://openstatus.dev) - Open-source monitoring platform
1472- [Documentation](https://docs.openstatus.dev) - Full API documentation
1473- [Status Page](https://status.openstatus.dev) - OpenStatus service status
1474
1475## License
1476
1477MIT