Openstatus sdk www.openstatus.dev
at export-client 1477 lines 38 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 { 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