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