Openstatus sdk www.openstatus.dev
at notification 1529 lines 39 kB view raw view rendered
1# OpenStatus Node.js SDK (Beta) 2 3[![JSR](https://jsr.io/badges/@openstatus/sdk-node)](https://jsr.io/@openstatus/sdk-node) 4[![npm](https://img.shields.io/npm/v/@openstatus/sdk-node)](https://www.npmjs.com/package/@openstatus/sdk-node) 5[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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