Openstatus sdk www.openstatus.dev
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix typo

+1953 -5
+5 -3
README.md
··· 28 28 - [Error Handling](#error-handling) 29 29 - [Related](#related) 30 30 31 + For comprehensive documentation, see [docs/index.md](docs/index.md). 32 + 31 33 ## Features 32 34 33 35 ### Monitoring ··· 279 281 List all monitors with pagination. Returns monitors grouped by type. 280 282 281 283 ```typescript 282 - const { httpMonitors, tcpMonitors, dnsMonitors, nextPageToken, totalSize } = 284 + const { httpMonitors, tcpMonitors, dnsMonitors, totalSize } = 283 285 await client.monitor.v1.MonitorService.listMonitors({ 284 - pageSize: 10, 285 - pageToken: "", 286 + limit: 10, 287 + offset: 0, 286 288 }); 287 289 ``` 288 290
+56
docs/authentication.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Authentication 4 + 5 + ## Recommended: createOpenStatusClient 6 + 7 + Create a client with your API key. The key is automatically included in all requests via an interceptor. 8 + 9 + ```typescript 10 + import { createOpenStatusClient } from "@openstatus/sdk-node"; 11 + 12 + const client = createOpenStatusClient({ 13 + apiKey: process.env.OPENSTATUS_API_KEY, 14 + }); 15 + 16 + // No headers needed on individual calls 17 + const { httpMonitors } = await client.monitor.v1.MonitorService.listMonitors({}); 18 + ``` 19 + 20 + ## Alternative: Manual Headers 21 + 22 + Use the default `openstatus` client and pass headers on each call. 23 + 24 + ```typescript 25 + import { openstatus } from "@openstatus/sdk-node"; 26 + 27 + const headers = { 28 + "x-openstatus-key": process.env.OPENSTATUS_API_KEY, 29 + }; 30 + 31 + await openstatus.monitor.v1.MonitorService.listMonitors({}, { headers }); 32 + ``` 33 + 34 + ## Environment Variables 35 + 36 + | Variable | Description | Default | 37 + |----------|-------------|---------| 38 + | `OPENSTATUS_API_KEY` | Your OpenStatus API key | Required for authenticated calls | 39 + | `OPENSTATUS_API_URL` | Custom API endpoint | `https://api.openstatus.dev/rpc` | 40 + 41 + Get your API key from the [OpenStatus dashboard](https://www.openstatus.dev/app). 42 + 43 + ## Custom Base URL 44 + 45 + For self-hosted instances or staging environments: 46 + 47 + ```typescript 48 + import { createOpenStatusClient } from "@openstatus/sdk-node"; 49 + 50 + const client = createOpenStatusClient({ 51 + apiKey: process.env.OPENSTATUS_API_KEY, 52 + baseUrl: "https://api.staging.example.com/rpc", 53 + }); 54 + ``` 55 + 56 + The `baseUrl` option takes precedence over the `OPENSTATUS_API_URL` environment variable.
+59
docs/error-handling.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Error Handling 4 + 5 + The SDK uses ConnectRPC. Errors are thrown as `ConnectError` instances from the `@connectrpc/connect` package. 6 + 7 + ```typescript 8 + import { ConnectError } from "@connectrpc/connect"; 9 + 10 + try { 11 + await client.monitor.v1.MonitorService.deleteMonitor({ id: "invalid" }); 12 + } catch (error) { 13 + if (error instanceof ConnectError) { 14 + console.error(`Code: ${error.code}`); 15 + console.error(`Message: ${error.message}`); 16 + } 17 + } 18 + ``` 19 + 20 + ## Common Error Codes 21 + 22 + | Code | Description | 23 + |------|-------------| 24 + | `unauthenticated` | Missing or invalid API key | 25 + | `not_found` | Resource does not exist | 26 + | `invalid_argument` | Validation failure (e.g., missing required field, value out of range) | 27 + | `permission_denied` | No access to this workspace or resource | 28 + | `already_exists` | Duplicate resource (e.g., slug already taken) | 29 + 30 + ## Retry Strategy 31 + 32 + ConnectRPC does not retry by default. For transient failures (`unavailable`, `deadline_exceeded`), implement your own retry logic: 33 + 34 + ```typescript 35 + import { ConnectError } from "@connectrpc/connect"; 36 + 37 + async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> { 38 + for (let attempt = 0; attempt <= maxRetries; attempt++) { 39 + try { 40 + return await fn(); 41 + } catch (error) { 42 + if ( 43 + error instanceof ConnectError && 44 + (error.code === "unavailable" || error.code === "deadline_exceeded") && 45 + attempt < maxRetries 46 + ) { 47 + await new Promise((resolve) => setTimeout(resolve, 1000 * 2 ** attempt)); 48 + continue; 49 + } 50 + throw error; 51 + } 52 + } 53 + throw new Error("Unreachable"); 54 + } 55 + 56 + const { httpMonitors } = await withRetry(() => 57 + client.monitor.v1.MonitorService.listMonitors({}) 58 + ); 59 + ```
+140
docs/getting-started.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Getting Started 4 + 5 + ## Installation 6 + 7 + ### npm 8 + 9 + ```bash 10 + npm install @openstatus/sdk-node 11 + ``` 12 + 13 + ### JSR 14 + 15 + ```bash 16 + npx jsr add @openstatus/sdk-node 17 + ``` 18 + 19 + ### Deno 20 + 21 + ```typescript 22 + import { createOpenStatusClient } from "jsr:@openstatus/sdk-node"; 23 + ``` 24 + 25 + ### Bun 26 + 27 + ```bash 28 + bun add @openstatus/sdk-node 29 + ``` 30 + 31 + ## Quick Start 32 + 33 + ```typescript 34 + import { 35 + createOpenStatusClient, 36 + Periodicity, 37 + Region, 38 + } from "@openstatus/sdk-node"; 39 + 40 + const client = createOpenStatusClient({ 41 + apiKey: process.env.OPENSTATUS_API_KEY, 42 + }); 43 + 44 + // Create an HTTP monitor 45 + const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({ 46 + monitor: { 47 + name: "My API", 48 + url: "https://api.example.com/health", 49 + periodicity: Periodicity.PERIODICITY_1M, 50 + regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD], 51 + active: true, 52 + }, 53 + }); 54 + 55 + console.log(`Monitor created: ${monitor?.id}`); 56 + 57 + // List all monitors 58 + const { httpMonitors, tcpMonitors, dnsMonitors, totalSize } = 59 + await client.monitor.v1.MonitorService.listMonitors({}); 60 + 61 + console.log(`Found ${totalSize} monitors`); 62 + ``` 63 + 64 + ## Runtime Support 65 + 66 + | Runtime | Version | Module Format | 67 + |---------|---------|---------------| 68 + | Node.js | >= 18 | ESM and CJS | 69 + | Deno | >= 2 | ESM (native) | 70 + | Bun | Latest | ESM | 71 + 72 + ## Full Workflow Example 73 + 74 + A complete example: create a monitor, set up a status page, add the monitor as a component, configure a Slack notification, and check overall status. 75 + 76 + ```typescript 77 + import { 78 + createOpenStatusClient, 79 + NotificationProvider, 80 + Periodicity, 81 + Region, 82 + } from "@openstatus/sdk-node"; 83 + 84 + const client = createOpenStatusClient({ 85 + apiKey: process.env.OPENSTATUS_API_KEY, 86 + }); 87 + 88 + // 1. Check API health 89 + const health = await client.health.v1.HealthService.check({}); 90 + console.log(`API status: ${health.status}`); 91 + 92 + // 2. Create an HTTP monitor 93 + const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({ 94 + monitor: { 95 + name: "Production API", 96 + url: "https://api.example.com/health", 97 + periodicity: Periodicity.PERIODICITY_1M, 98 + regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD], 99 + active: true, 100 + }, 101 + }); 102 + 103 + // 3. Create a status page 104 + const { statusPage } = await client.statusPage.v1.StatusPageService 105 + .createStatusPage({ 106 + title: "Example Status", 107 + slug: "example-status", 108 + description: "Status page for Example services", 109 + }); 110 + 111 + // 4. Add the monitor as a component 112 + const { component } = await client.statusPage.v1.StatusPageService 113 + .addMonitorComponent({ 114 + pageId: statusPage!.id, 115 + monitorId: monitor!.id, 116 + name: "Production API", 117 + }); 118 + 119 + // 5. Set up Slack notifications 120 + const { notification } = await client.notification.v1.NotificationService 121 + .createNotification({ 122 + name: "Slack Alerts", 123 + provider: NotificationProvider.SLACK, 124 + data: { 125 + data: { 126 + case: "slack", 127 + value: { webhookUrl: "https://hooks.slack.com/services/..." }, 128 + }, 129 + }, 130 + monitorIds: [monitor!.id], 131 + }); 132 + 133 + // 6. Check overall status 134 + const { overallStatus } = await client.statusPage.v1.StatusPageService 135 + .getOverallStatus({ 136 + identifier: { case: "id", value: statusPage!.id }, 137 + }); 138 + 139 + console.log(`Overall status: ${overallStatus}`); 140 + ```
+22
docs/health-service.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Health Service 4 + 5 + Check API health status. No authentication required. 6 + 7 + ```typescript 8 + import { openstatus, ServingStatus } from "@openstatus/sdk-node"; 9 + 10 + const { status } = await openstatus.health.v1.HealthService.check({}); 11 + console.log(ServingStatus[status]); // "SERVING" 12 + ``` 13 + 14 + Or with a configured client: 15 + 16 + ```typescript 17 + import { createOpenStatusClient, ServingStatus } from "@openstatus/sdk-node"; 18 + 19 + const client = createOpenStatusClient(); 20 + const { status } = await client.health.v1.HealthService.check({}); 21 + console.log(ServingStatus[status]); // "SERVING" 22 + ```
+65
docs/index.md
··· 1 + # OpenStatus Node.js SDK Documentation 2 + 3 + Official documentation for [`@openstatus/sdk-node`](https://www.npmjs.com/package/@openstatus/sdk-node) — the TypeScript SDK for the [OpenStatus](https://openstatus.dev) monitoring platform. 4 + 5 + --- 6 + 7 + ## Table of Contents 8 + 9 + - [Getting Started](./getting-started.md) 10 + - Installation 11 + - Quick Start 12 + - Runtime Support 13 + - Full Workflow Example 14 + - [Authentication](./authentication.md) 15 + - createOpenStatusClient 16 + - Manual Headers 17 + - Environment Variables 18 + - Custom Base URL 19 + - [Monitor Service](./monitor-service.md) 20 + - HTTP Monitors 21 + - TCP Monitors 22 + - DNS Monitors 23 + - List Monitors 24 + - Get Monitor 25 + - Trigger Monitor 26 + - Delete Monitor 27 + - Get Monitor Status 28 + - Get Monitor Summary 29 + - [Status Page Service](./status-page-service.md) 30 + - Status Page CRUD 31 + - Components 32 + - Component Groups 33 + - Subscribers 34 + - Get Status Page Content 35 + - Get Overall Status 36 + - [Status Report Service](./status-report-service.md) 37 + - Create Status Report 38 + - Add Status Report Update 39 + - List Status Reports 40 + - Get / Update / Delete Status Reports 41 + - [Maintenance Service](./maintenance-service.md) 42 + - Create Maintenance Window 43 + - List Maintenances 44 + - Get / Update / Delete Maintenance Windows 45 + - [Notification Service](./notification-service.md) 46 + - Create Notification 47 + - Provider Configurations 48 + - Send Test Notification 49 + - Check Notification Limits 50 + - List / Get / Update / Delete Notifications 51 + - [Health Service](./health-service.md) 52 + - Health Check 53 + - [Reference](./reference.md) 54 + - Enums 55 + - Regions 56 + - Assertions 57 + - TypeScript Type Exports 58 + - [Error Handling](./error-handling.md) 59 + - ConnectError 60 + - Common Error Codes 61 + - Retry Strategy 62 + - [TypeScript Tips](./typescript-tips.md) 63 + - Working with bigint Fields 64 + - Handling oneof Types 65 + - Migrating from Default Client to createOpenStatusClient
+70
docs/maintenance-service.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Maintenance Service 4 + 5 + Manage scheduled maintenance windows. The Maintenance Service provides 5 RPC methods. 6 + 7 + ## Create Maintenance Window 8 + 9 + ```typescript 10 + const { maintenance } = await client.maintenance.v1.MaintenanceService 11 + .createMaintenance({ 12 + title: "Database Upgrade", 13 + message: "We will be upgrading our database infrastructure.", 14 + from: "2024-01-20T02:00:00Z", 15 + to: "2024-01-20T04:00:00Z", 16 + pageId: "page_123", 17 + pageComponentIds: ["comp_456"], 18 + notify: true, 19 + }); 20 + 21 + console.log(`Maintenance created: ${maintenance?.id}`); 22 + ``` 23 + 24 + All date fields (`from`, `to`) must be in RFC 3339 format. 25 + 26 + ## List Maintenances 27 + 28 + List maintenance windows with optional page filtering. 29 + 30 + ```typescript 31 + const { maintenances, totalSize } = await client.maintenance.v1 32 + .MaintenanceService.listMaintenances({ 33 + limit: 10, 34 + offset: 0, 35 + pageId: "page_123", 36 + }); 37 + 38 + console.log(`Found ${totalSize} maintenance windows`); 39 + ``` 40 + 41 + ## Get / Update / Delete Maintenance Windows 42 + 43 + ### Get Maintenance 44 + 45 + ```typescript 46 + const { maintenance } = await client.maintenance.v1.MaintenanceService 47 + .getMaintenance({ id: "maint_123" }); 48 + 49 + console.log(`Title: ${maintenance?.title}`); 50 + console.log(`From: ${maintenance?.from}`); 51 + console.log(`To: ${maintenance?.to}`); 52 + ``` 53 + 54 + ### Update Maintenance 55 + 56 + ```typescript 57 + const { maintenance } = await client.maintenance.v1.MaintenanceService 58 + .updateMaintenance({ 59 + id: "maint_123", 60 + title: "Extended Database Upgrade", 61 + to: "2024-01-20T06:00:00Z", 62 + }); 63 + ``` 64 + 65 + ### Delete Maintenance 66 + 67 + ```typescript 68 + const { success } = await client.maintenance.v1.MaintenanceService 69 + .deleteMaintenance({ id: "maint_123" }); 70 + ```
+346
docs/monitor-service.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Monitor Service 4 + 5 + Manage HTTP, TCP, and DNS monitors. The Monitor Service provides 12 RPC methods for creating, updating, listing, triggering, deleting, and querying monitor status and metrics. 6 + 7 + All examples assume you have created a client: 8 + 9 + ```typescript 10 + import { createOpenStatusClient } from "@openstatus/sdk-node"; 11 + 12 + const client = createOpenStatusClient({ 13 + apiKey: process.env.OPENSTATUS_API_KEY, 14 + }); 15 + ``` 16 + 17 + ## HTTP Monitors 18 + 19 + ### Create HTTP Monitor 20 + 21 + ```typescript 22 + import { 23 + createOpenStatusClient, 24 + HTTPMethod, 25 + NumberComparator, 26 + Periodicity, 27 + Region, 28 + StringComparator, 29 + } from "@openstatus/sdk-node"; 30 + 31 + const client = createOpenStatusClient({ 32 + apiKey: process.env.OPENSTATUS_API_KEY, 33 + }); 34 + 35 + const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({ 36 + monitor: { 37 + name: "My API", 38 + url: "https://api.example.com/health", 39 + periodicity: Periodicity.PERIODICITY_1M, 40 + method: HTTPMethod.HTTP_METHOD_GET, 41 + regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD], 42 + active: true, 43 + timeout: BigInt(30000), 44 + retry: BigInt(3), 45 + followRedirects: true, 46 + degradedAt: BigInt(5000), 47 + headers: [ 48 + { key: "Authorization", value: "Bearer my-token" }, 49 + ], 50 + statusCodeAssertions: [ 51 + { comparator: NumberComparator.EQUAL, target: BigInt(200) }, 52 + ], 53 + bodyAssertions: [ 54 + { comparator: StringComparator.CONTAINS, target: '"status":"ok"' }, 55 + ], 56 + headerAssertions: [ 57 + { 58 + key: "content-type", 59 + comparator: StringComparator.CONTAINS, 60 + target: "application/json", 61 + }, 62 + ], 63 + description: "Health check for the production API", 64 + public: false, 65 + openTelemetry: { 66 + endpoint: "https://otel.example.com/v1/traces", 67 + headers: [{ key: "Authorization", value: "Bearer otel-token" }], 68 + }, 69 + }, 70 + }); 71 + 72 + console.log(`Created monitor: ${monitor?.id}`); 73 + ``` 74 + 75 + ### Update HTTP Monitor 76 + 77 + Updates are partial — only include the fields you want to change. 78 + 79 + ```typescript 80 + const { monitor } = await client.monitor.v1.MonitorService.updateHTTPMonitor({ 81 + id: "mon_123", 82 + monitor: { 83 + name: "Updated API Monitor", 84 + active: false, 85 + }, 86 + }); 87 + ``` 88 + 89 + ### HTTP Monitor Options 90 + 91 + | Option | Type | Required | Description | 92 + |--------|------|----------|-------------| 93 + | `name` | string | Yes | Monitor name (max 256 chars) | 94 + | `url` | string | Yes | URL to monitor (max 2048 chars) | 95 + | `periodicity` | Periodicity | Yes | Check interval | 96 + | `method` | HTTPMethod | No | HTTP method (default: GET) | 97 + | `body` | string | No | Request body | 98 + | `headers` | Headers[] | No | Custom headers `{ key, value }[]` | 99 + | `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) | 100 + | `retry` | bigint | No | Retry attempts (default: 3, max: 10) | 101 + | `followRedirects` | boolean | No | Follow redirects (default: true) | 102 + | `regions` | Region[] | No | Regions for checks | 103 + | `active` | boolean | No | Enable monitoring (default: false) | 104 + | `public` | boolean | No | Public visibility (default: false) | 105 + | `degradedAt` | bigint | No | Latency threshold (ms) for degraded status | 106 + | `description` | string | No | Monitor description (max 1024 chars) | 107 + | `statusCodeAssertions` | StatusCodeAssertion[] | No | Status code assertions | 108 + | `bodyAssertions` | BodyAssertion[] | No | Body assertions | 109 + | `headerAssertions` | HeaderAssertion[] | No | Header assertions | 110 + | `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration | 111 + 112 + ## TCP Monitors 113 + 114 + ### Create TCP Monitor 115 + 116 + ```typescript 117 + import { 118 + createOpenStatusClient, 119 + Periodicity, 120 + Region, 121 + } from "@openstatus/sdk-node"; 122 + 123 + const client = createOpenStatusClient({ 124 + apiKey: process.env.OPENSTATUS_API_KEY, 125 + }); 126 + 127 + const { monitor } = await client.monitor.v1.MonitorService.createTCPMonitor({ 128 + monitor: { 129 + name: "Database", 130 + uri: "db.example.com:5432", 131 + periodicity: Periodicity.PERIODICITY_5M, 132 + regions: [Region.FLY_AMS, Region.FLY_IAD], 133 + active: true, 134 + }, 135 + }); 136 + ``` 137 + 138 + ### Update TCP Monitor 139 + 140 + ```typescript 141 + const { monitor } = await client.monitor.v1.MonitorService.updateTCPMonitor({ 142 + id: "mon_123", 143 + monitor: { 144 + name: "Updated Database Monitor", 145 + }, 146 + }); 147 + ``` 148 + 149 + ### TCP Monitor Options 150 + 151 + | Option | Type | Required | Description | 152 + |--------|------|----------|-------------| 153 + | `name` | string | Yes | Monitor name (max 256 chars) | 154 + | `uri` | string | Yes | `host:port` to monitor (max 2048 chars) | 155 + | `periodicity` | Periodicity | Yes | Check interval | 156 + | `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) | 157 + | `retry` | bigint | No | Retry attempts (default: 3, max: 10) | 158 + | `regions` | Region[] | No | Regions for checks | 159 + | `active` | boolean | No | Enable monitoring (default: false) | 160 + | `public` | boolean | No | Public visibility (default: false) | 161 + | `degradedAt` | bigint | No | Latency threshold (ms) for degraded status | 162 + | `description` | string | No | Monitor description (max 1024 chars) | 163 + | `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration | 164 + 165 + ## DNS Monitors 166 + 167 + ### Create DNS Monitor 168 + 169 + ```typescript 170 + import { 171 + createOpenStatusClient, 172 + Periodicity, 173 + RecordComparator, 174 + Region, 175 + } from "@openstatus/sdk-node"; 176 + 177 + const client = createOpenStatusClient({ 178 + apiKey: process.env.OPENSTATUS_API_KEY, 179 + }); 180 + 181 + const { monitor } = await client.monitor.v1.MonitorService.createDNSMonitor({ 182 + monitor: { 183 + name: "DNS Check", 184 + uri: "example.com", 185 + periodicity: Periodicity.PERIODICITY_10M, 186 + regions: [Region.FLY_AMS], 187 + active: true, 188 + recordAssertions: [ 189 + { 190 + record: "A", 191 + comparator: RecordComparator.EQUAL, 192 + target: "93.184.216.34", 193 + }, 194 + { 195 + record: "CNAME", 196 + comparator: RecordComparator.CONTAINS, 197 + target: "cdn", 198 + }, 199 + ], 200 + }, 201 + }); 202 + ``` 203 + 204 + ### Update DNS Monitor 205 + 206 + ```typescript 207 + const { monitor } = await client.monitor.v1.MonitorService.updateDNSMonitor({ 208 + id: "mon_123", 209 + monitor: { 210 + name: "Updated DNS Check", 211 + }, 212 + }); 213 + ``` 214 + 215 + ### DNS Monitor Options 216 + 217 + | Option | Type | Required | Description | 218 + |--------|------|----------|-------------| 219 + | `name` | string | Yes | Monitor name (max 256 chars) | 220 + | `uri` | string | Yes | Domain to resolve (max 2048 chars) | 221 + | `periodicity` | Periodicity | Yes | Check interval | 222 + | `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) | 223 + | `retry` | bigint | No | Retry attempts (default: 3, max: 10) | 224 + | `regions` | Region[] | No | Regions for checks | 225 + | `active` | boolean | No | Enable monitoring (default: false) | 226 + | `public` | boolean | No | Public visibility (default: false) | 227 + | `degradedAt` | bigint | No | Latency threshold (ms) for degraded status | 228 + | `description` | string | No | Monitor description (max 1024 chars) | 229 + | `recordAssertions` | RecordAssertion[] | No | DNS record assertions | 230 + | `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration | 231 + 232 + ## List Monitors 233 + 234 + List all monitors with offset-based pagination. Returns monitors grouped by type. 235 + 236 + ```typescript 237 + const { httpMonitors, tcpMonitors, dnsMonitors, totalSize } = 238 + await client.monitor.v1.MonitorService.listMonitors({ 239 + limit: 10, 240 + offset: 0, 241 + }); 242 + 243 + console.log(`Total: ${totalSize}`); 244 + console.log(`HTTP: ${httpMonitors.length}`); 245 + console.log(`TCP: ${tcpMonitors.length}`); 246 + console.log(`DNS: ${dnsMonitors.length}`); 247 + ``` 248 + 249 + Pagination parameters: 250 + 251 + | Parameter | Type | Description | 252 + |-----------|------|-------------| 253 + | `limit` | number (optional) | Max results to return (1–100, default 50) | 254 + | `offset` | number (optional) | Number of results to skip (default 0) | 255 + 256 + ## Get Monitor 257 + 258 + Get a single monitor by ID. The response uses a `MonitorConfig` oneof type that contains one of HTTP, TCP, or DNS configuration. 259 + 260 + ```typescript 261 + const { monitor } = await client.monitor.v1.MonitorService.getMonitor({ 262 + id: "mon_123", 263 + }); 264 + 265 + if (monitor?.config.case === "http") { 266 + console.log(`HTTP Monitor: ${monitor.config.value.name} — ${monitor.config.value.url}`); 267 + } else if (monitor?.config.case === "tcp") { 268 + console.log(`TCP Monitor: ${monitor.config.value.name} — ${monitor.config.value.uri}`); 269 + } else if (monitor?.config.case === "dns") { 270 + console.log(`DNS Monitor: ${monitor.config.value.name} — ${monitor.config.value.uri}`); 271 + } 272 + ``` 273 + 274 + ## Trigger Monitor 275 + 276 + Trigger an immediate check for a monitor. 277 + 278 + ```typescript 279 + const { success } = await client.monitor.v1.MonitorService.triggerMonitor({ 280 + id: "mon_123", 281 + }); 282 + 283 + console.log(`Trigger successful: ${success}`); 284 + ``` 285 + 286 + ## Delete Monitor 287 + 288 + ```typescript 289 + const { success } = await client.monitor.v1.MonitorService.deleteMonitor({ 290 + id: "mon_123", 291 + }); 292 + ``` 293 + 294 + ## Get Monitor Status 295 + 296 + Get the current status of a monitor across all configured regions. 297 + 298 + ```typescript 299 + import { 300 + createOpenStatusClient, 301 + MonitorStatus, 302 + Region, 303 + } from "@openstatus/sdk-node"; 304 + 305 + const client = createOpenStatusClient({ 306 + apiKey: process.env.OPENSTATUS_API_KEY, 307 + }); 308 + 309 + const { id, regions } = await client.monitor.v1.MonitorService.getMonitorStatus( 310 + { id: "mon_123" }, 311 + ); 312 + 313 + for (const { region, status } of regions) { 314 + console.log(`${Region[region]}: ${MonitorStatus[status]}`); 315 + } 316 + ``` 317 + 318 + ## Get Monitor Summary 319 + 320 + Get aggregated metrics and latency percentiles for a monitor over a time range. 321 + 322 + ```typescript 323 + import { createOpenStatusClient, TimeRange } from "@openstatus/sdk-node"; 324 + 325 + const client = createOpenStatusClient({ 326 + apiKey: process.env.OPENSTATUS_API_KEY, 327 + }); 328 + 329 + const summary = await client.monitor.v1.MonitorService.getMonitorSummary({ 330 + id: "mon_123", 331 + timeRange: TimeRange.TIME_RANGE_7D, 332 + regions: [], 333 + }); 334 + 335 + console.log(`Last ping: ${summary.lastPingAt}`); 336 + console.log(`Successful: ${summary.totalSuccessful}`); 337 + console.log(`Degraded: ${summary.totalDegraded}`); 338 + console.log(`Failed: ${summary.totalFailed}`); 339 + console.log(`P50: ${summary.p50}ms`); 340 + console.log(`P75: ${summary.p75}ms`); 341 + console.log(`P90: ${summary.p90}ms`); 342 + console.log(`P95: ${summary.p95}ms`); 343 + console.log(`P99: ${summary.p99}ms`); 344 + ``` 345 + 346 + The latency fields (`p50`, `p75`, `p90`, `p95`, `p99`) and count fields (`totalSuccessful`, `totalDegraded`, `totalFailed`) are `bigint` values. The `regions` parameter is optional — pass an empty array to get metrics across all regions.
+335
docs/notification-service.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Notification Service 4 + 5 + Manage notification channels for monitor alerts. Supports 12 providers. The Notification Service provides 7 RPC methods. 6 + 7 + ## Create Notification 8 + 9 + ```typescript 10 + import { 11 + createOpenStatusClient, 12 + NotificationProvider, 13 + } from "@openstatus/sdk-node"; 14 + 15 + const client = createOpenStatusClient({ 16 + apiKey: process.env.OPENSTATUS_API_KEY, 17 + }); 18 + 19 + const { notification } = await client.notification.v1.NotificationService 20 + .createNotification({ 21 + name: "Slack Alerts", 22 + provider: NotificationProvider.SLACK, 23 + data: { 24 + data: { 25 + case: "slack", 26 + value: { webhookUrl: "https://hooks.slack.com/services/..." }, 27 + }, 28 + }, 29 + monitorIds: ["mon_123", "mon_456"], 30 + }); 31 + 32 + console.log(`Notification created: ${notification?.id}`); 33 + ``` 34 + 35 + The `data` field uses a nested oneof pattern: the outer `data` is the `NotificationData` message, and `data.data` is the oneof that selects the provider-specific configuration. The `case` must match the provider type in lowercase. 36 + 37 + ## Provider Configurations 38 + 39 + Each provider shown as a complete `createNotification` call. 40 + 41 + ### Slack 42 + 43 + ```typescript 44 + const { notification } = await client.notification.v1.NotificationService 45 + .createNotification({ 46 + name: "Slack Alerts", 47 + provider: NotificationProvider.SLACK, 48 + data: { 49 + data: { 50 + case: "slack", 51 + value: { webhookUrl: "https://hooks.slack.com/services/..." }, 52 + }, 53 + }, 54 + monitorIds: ["mon_123"], 55 + }); 56 + ``` 57 + 58 + ### Discord 59 + 60 + ```typescript 61 + const { notification } = await client.notification.v1.NotificationService 62 + .createNotification({ 63 + name: "Discord Alerts", 64 + provider: NotificationProvider.DISCORD, 65 + data: { 66 + data: { 67 + case: "discord", 68 + value: { webhookUrl: "https://discord.com/api/webhooks/..." }, 69 + }, 70 + }, 71 + monitorIds: ["mon_123"], 72 + }); 73 + ``` 74 + 75 + ### Email 76 + 77 + ```typescript 78 + const { notification } = await client.notification.v1.NotificationService 79 + .createNotification({ 80 + name: "Email Alerts", 81 + provider: NotificationProvider.EMAIL, 82 + data: { 83 + data: { 84 + case: "email", 85 + value: { email: "alerts@example.com" }, 86 + }, 87 + }, 88 + monitorIds: ["mon_123"], 89 + }); 90 + ``` 91 + 92 + ### PagerDuty 93 + 94 + ```typescript 95 + const { notification } = await client.notification.v1.NotificationService 96 + .createNotification({ 97 + name: "PagerDuty Alerts", 98 + provider: NotificationProvider.PAGERDUTY, 99 + data: { 100 + data: { 101 + case: "pagerduty", 102 + value: { integrationKey: "your-integration-key" }, 103 + }, 104 + }, 105 + monitorIds: ["mon_123"], 106 + }); 107 + ``` 108 + 109 + ### Opsgenie 110 + 111 + ```typescript 112 + import { NotificationProvider, OpsgenieRegion } from "@openstatus/sdk-node"; 113 + 114 + const { notification } = await client.notification.v1.NotificationService 115 + .createNotification({ 116 + name: "Opsgenie Alerts", 117 + provider: NotificationProvider.OPSGENIE, 118 + data: { 119 + data: { 120 + case: "opsgenie", 121 + value: { apiKey: "your-api-key", region: OpsgenieRegion.US }, 122 + }, 123 + }, 124 + monitorIds: ["mon_123"], 125 + }); 126 + ``` 127 + 128 + ### Telegram 129 + 130 + ```typescript 131 + const { notification } = await client.notification.v1.NotificationService 132 + .createNotification({ 133 + name: "Telegram Alerts", 134 + provider: NotificationProvider.TELEGRAM, 135 + data: { 136 + data: { 137 + case: "telegram", 138 + value: { chatId: "123456789" }, 139 + }, 140 + }, 141 + monitorIds: ["mon_123"], 142 + }); 143 + ``` 144 + 145 + ### Google Chat 146 + 147 + ```typescript 148 + const { notification } = await client.notification.v1.NotificationService 149 + .createNotification({ 150 + name: "Google Chat Alerts", 151 + provider: NotificationProvider.GOOGLE_CHAT, 152 + data: { 153 + data: { 154 + case: "googleChat", 155 + value: { webhookUrl: "https://chat.googleapis.com/v1/spaces/..." }, 156 + }, 157 + }, 158 + monitorIds: ["mon_123"], 159 + }); 160 + ``` 161 + 162 + ### Grafana OnCall 163 + 164 + ```typescript 165 + const { notification } = await client.notification.v1.NotificationService 166 + .createNotification({ 167 + name: "Grafana OnCall", 168 + provider: NotificationProvider.GRAFANA_ONCALL, 169 + data: { 170 + data: { 171 + case: "grafanaOncall", 172 + value: { webhookUrl: "https://oncall.example.com/..." }, 173 + }, 174 + }, 175 + monitorIds: ["mon_123"], 176 + }); 177 + ``` 178 + 179 + ### Ntfy 180 + 181 + ```typescript 182 + const { notification } = await client.notification.v1.NotificationService 183 + .createNotification({ 184 + name: "Ntfy Alerts", 185 + provider: NotificationProvider.NTFY, 186 + data: { 187 + data: { 188 + case: "ntfy", 189 + value: { 190 + topic: "my-alerts", 191 + serverUrl: "https://ntfy.sh", 192 + token: "tk_...", 193 + }, 194 + }, 195 + }, 196 + monitorIds: ["mon_123"], 197 + }); 198 + ``` 199 + 200 + ### SMS 201 + 202 + ```typescript 203 + const { notification } = await client.notification.v1.NotificationService 204 + .createNotification({ 205 + name: "SMS Alerts", 206 + provider: NotificationProvider.SMS, 207 + data: { 208 + data: { 209 + case: "sms", 210 + value: { phoneNumber: "+1234567890" }, 211 + }, 212 + }, 213 + monitorIds: ["mon_123"], 214 + }); 215 + ``` 216 + 217 + ### WhatsApp 218 + 219 + ```typescript 220 + const { notification } = await client.notification.v1.NotificationService 221 + .createNotification({ 222 + name: "WhatsApp Alerts", 223 + provider: NotificationProvider.WHATSAPP, 224 + data: { 225 + data: { 226 + case: "whatsapp", 227 + value: { phoneNumber: "+1234567890" }, 228 + }, 229 + }, 230 + monitorIds: ["mon_123"], 231 + }); 232 + ``` 233 + 234 + ### Custom Webhook 235 + 236 + ```typescript 237 + const { notification } = await client.notification.v1.NotificationService 238 + .createNotification({ 239 + name: "Custom Webhook", 240 + provider: NotificationProvider.WEBHOOK, 241 + data: { 242 + data: { 243 + case: "webhook", 244 + value: { 245 + endpoint: "https://api.example.com/webhook", 246 + headers: [ 247 + { key: "Authorization", value: "Bearer token" }, 248 + { key: "X-Custom-Header", value: "value" }, 249 + ], 250 + }, 251 + }, 252 + }, 253 + monitorIds: ["mon_123"], 254 + }); 255 + ``` 256 + 257 + ## Send Test Notification 258 + 259 + Verify a notification configuration without creating a channel. 260 + 261 + ```typescript 262 + import { NotificationProvider } from "@openstatus/sdk-node"; 263 + 264 + const { success, errorMessage } = await client.notification.v1 265 + .NotificationService.sendTestNotification({ 266 + provider: NotificationProvider.SLACK, 267 + data: { 268 + data: { 269 + case: "slack", 270 + value: { webhookUrl: "https://hooks.slack.com/services/..." }, 271 + }, 272 + }, 273 + }); 274 + 275 + if (success) { 276 + console.log("Test notification sent successfully"); 277 + } else { 278 + console.log(`Test failed: ${errorMessage}`); 279 + } 280 + ``` 281 + 282 + ## Check Notification Limits 283 + 284 + Check if the workspace has reached its notification channel limit. 285 + 286 + ```typescript 287 + const { limitReached, currentCount, maxCount } = await client.notification.v1 288 + .NotificationService.checkNotificationLimit({}); 289 + 290 + console.log(`${currentCount}/${maxCount} notification channels used`); 291 + if (limitReached) { 292 + console.log("Notification limit reached — upgrade your plan"); 293 + } 294 + ``` 295 + 296 + ## List / Get / Update / Delete Notifications 297 + 298 + ### List Notifications 299 + 300 + ```typescript 301 + const { notifications, totalSize } = await client.notification.v1 302 + .NotificationService.listNotifications({ limit: 10, offset: 0 }); 303 + 304 + console.log(`Found ${totalSize} notification channels`); 305 + ``` 306 + 307 + ### Get Notification 308 + 309 + ```typescript 310 + import { NotificationProvider } from "@openstatus/sdk-node"; 311 + 312 + const { notification } = await client.notification.v1.NotificationService 313 + .getNotification({ id: "notif_123" }); 314 + 315 + console.log(`Name: ${notification?.name}`); 316 + console.log(`Provider: ${NotificationProvider[notification?.provider ?? 0]}`); 317 + ``` 318 + 319 + ### Update Notification 320 + 321 + ```typescript 322 + const { notification } = await client.notification.v1.NotificationService 323 + .updateNotification({ 324 + id: "notif_123", 325 + name: "Updated Slack Alerts", 326 + monitorIds: ["mon_123", "mon_456", "mon_789"], 327 + }); 328 + ``` 329 + 330 + ### Delete Notification 331 + 332 + ```typescript 333 + const { success } = await client.notification.v1.NotificationService 334 + .deleteNotification({ id: "notif_123" }); 335 + ```
+374
docs/reference.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Reference 4 + 5 + ## Enums 6 + 7 + ### Periodicity 8 + 9 + | Value | Description | 10 + |-------|-------------| 11 + | `PERIODICITY_30S` | Every 30 seconds | 12 + | `PERIODICITY_1M` | Every 1 minute | 13 + | `PERIODICITY_5M` | Every 5 minutes | 14 + | `PERIODICITY_10M` | Every 10 minutes | 15 + | `PERIODICITY_30M` | Every 30 minutes | 16 + | `PERIODICITY_1H` | Every 1 hour | 17 + 18 + ### HTTPMethod 19 + 20 + | Value | Description | 21 + |-------|-------------| 22 + | `HTTP_METHOD_GET` | GET | 23 + | `HTTP_METHOD_POST` | POST | 24 + | `HTTP_METHOD_HEAD` | HEAD | 25 + | `HTTP_METHOD_PUT` | PUT | 26 + | `HTTP_METHOD_PATCH` | PATCH | 27 + | `HTTP_METHOD_DELETE` | DELETE | 28 + | `HTTP_METHOD_TRACE` | TRACE | 29 + | `HTTP_METHOD_CONNECT` | CONNECT | 30 + | `HTTP_METHOD_OPTIONS` | OPTIONS | 31 + 32 + ### MonitorStatus 33 + 34 + | Value | Description | 35 + |-------|-------------| 36 + | `ACTIVE` | Monitor is healthy | 37 + | `DEGRADED` | Latency threshold exceeded | 38 + | `ERROR` | Monitor is failing | 39 + 40 + ### TimeRange 41 + 42 + | Value | Description | 43 + |-------|-------------| 44 + | `TIME_RANGE_1D` | Last 24 hours | 45 + | `TIME_RANGE_7D` | Last 7 days | 46 + | `TIME_RANGE_14D` | Last 14 days | 47 + 48 + ### StatusReportStatus 49 + 50 + | Value | Description | 51 + |-------|-------------| 52 + | `INVESTIGATING` | Actively investigating the issue | 53 + | `IDENTIFIED` | Root cause has been identified | 54 + | `MONITORING` | Fix deployed, monitoring | 55 + | `RESOLVED` | Issue fully resolved | 56 + 57 + ### OverallStatus 58 + 59 + | Value | Description | 60 + |-------|-------------| 61 + | `OPERATIONAL` | All systems operational | 62 + | `DEGRADED` | Performance is degraded | 63 + | `PARTIAL_OUTAGE` | Some systems are down | 64 + | `MAJOR_OUTAGE` | Major systems are down | 65 + | `MAINTENANCE` | Scheduled maintenance | 66 + | `UNKNOWN` | Status cannot be determined | 67 + 68 + ### NotificationProvider 69 + 70 + | Value | Description | 71 + |-------|-------------| 72 + | `DISCORD` | Discord webhook | 73 + | `EMAIL` | Email notification | 74 + | `GOOGLE_CHAT` | Google Chat webhook | 75 + | `GRAFANA_ONCALL` | Grafana OnCall | 76 + | `NTFY` | Ntfy push service | 77 + | `PAGERDUTY` | PagerDuty | 78 + | `OPSGENIE` | Opsgenie | 79 + | `SLACK` | Slack webhook | 80 + | `SMS` | SMS notification | 81 + | `TELEGRAM` | Telegram bot | 82 + | `WEBHOOK` | Custom webhook | 83 + | `WHATSAPP` | WhatsApp | 84 + 85 + ### OpsgenieRegion 86 + 87 + | Value | Description | 88 + |-------|-------------| 89 + | `US` | US region | 90 + | `EU` | EU region | 91 + 92 + ### PageAccessType 93 + 94 + | Value | Description | 95 + |-------|-------------| 96 + | `PUBLIC` | Publicly accessible | 97 + | `PASSWORD_PROTECTED` | Requires password | 98 + | `AUTHENTICATED` | Requires authentication | 99 + 100 + ### PageTheme 101 + 102 + | Value | Description | 103 + |-------|-------------| 104 + | `SYSTEM` | Follow system theme | 105 + | `LIGHT` | Light theme | 106 + | `DARK` | Dark theme | 107 + 108 + ### PageComponentType 109 + 110 + | Value | Description | 111 + |-------|-------------| 112 + | `MONITOR` | Linked to a monitor | 113 + | `STATIC` | Static component (manual) | 114 + 115 + ### NumberComparator 116 + 117 + | Value | Description | 118 + |-------|-------------| 119 + | `EQUAL` | Equal to target | 120 + | `NOT_EQUAL` | Not equal to target | 121 + | `GREATER_THAN` | Greater than target | 122 + | `GREATER_THAN_OR_EQUAL` | Greater than or equal | 123 + | `LESS_THAN` | Less than target | 124 + | `LESS_THAN_OR_EQUAL` | Less than or equal | 125 + 126 + ### StringComparator 127 + 128 + | Value | Description | 129 + |-------|-------------| 130 + | `CONTAINS` | Contains target string | 131 + | `NOT_CONTAINS` | Does not contain target | 132 + | `EQUAL` | Equal to target | 133 + | `NOT_EQUAL` | Not equal to target | 134 + | `EMPTY` | Value is empty | 135 + | `NOT_EMPTY` | Value is not empty | 136 + | `GREATER_THAN` | Lexicographically greater | 137 + | `GREATER_THAN_OR_EQUAL` | Lexicographically >= target | 138 + | `LESS_THAN` | Lexicographically less | 139 + | `LESS_THAN_OR_EQUAL` | Lexicographically <= target | 140 + 141 + ### RecordComparator 142 + 143 + | Value | Description | 144 + |-------|-------------| 145 + | `EQUAL` | Equal to target | 146 + | `NOT_EQUAL` | Not equal to target | 147 + | `CONTAINS` | Contains target string | 148 + | `NOT_CONTAINS` | Does not contain target | 149 + 150 + ### ServingStatus 151 + 152 + | Value | Description | 153 + |-------|-------------| 154 + | `SERVING` | Service is healthy and serving | 155 + | `NOT_SERVING` | Service is not healthy | 156 + 157 + ## Regions 158 + 159 + Monitor from 28 global locations across multiple providers. 160 + 161 + ```typescript 162 + import { Region } from "@openstatus/sdk-node"; 163 + 164 + regions: [Region.FLY_AMS, Region.FLY_IAD, Region.KOYEB_FRA]; 165 + ``` 166 + 167 + ### Fly.io Regions (18) 168 + 169 + | Enum Value | Location | 170 + |------------|----------| 171 + | `FLY_AMS` | Amsterdam | 172 + | `FLY_ARN` | Stockholm | 173 + | `FLY_BOM` | Mumbai | 174 + | `FLY_CDG` | Paris | 175 + | `FLY_DFW` | Dallas | 176 + | `FLY_EWR` | Newark | 177 + | `FLY_FRA` | Frankfurt | 178 + | `FLY_GRU` | São Paulo | 179 + | `FLY_IAD` | Washington D.C. | 180 + | `FLY_JNB` | Johannesburg | 181 + | `FLY_LAX` | Los Angeles | 182 + | `FLY_LHR` | London | 183 + | `FLY_NRT` | Tokyo | 184 + | `FLY_ORD` | Chicago | 185 + | `FLY_SJC` | San Jose | 186 + | `FLY_SIN` | Singapore | 187 + | `FLY_SYD` | Sydney | 188 + | `FLY_YYZ` | Toronto | 189 + 190 + ### Koyeb Regions (6) 191 + 192 + | Enum Value | Location | 193 + |------------|----------| 194 + | `KOYEB_FRA` | Frankfurt | 195 + | `KOYEB_PAR` | Paris | 196 + | `KOYEB_SFO` | San Francisco | 197 + | `KOYEB_SIN` | Singapore | 198 + | `KOYEB_TYO` | Tokyo | 199 + | `KOYEB_WAS` | Washington | 200 + 201 + ### Railway Regions (4) 202 + 203 + | Enum Value | Location | 204 + |------------|----------| 205 + | `RAILWAY_US_WEST2` | US West | 206 + | `RAILWAY_US_EAST4` | US East | 207 + | `RAILWAY_EUROPE_WEST4` | Europe West | 208 + | `RAILWAY_ASIA_SOUTHEAST1` | Asia Southeast | 209 + 210 + ## Assertions 211 + 212 + ### Status Code Assertions 213 + 214 + Validate HTTP response status codes using `NumberComparator`. 215 + 216 + ```typescript 217 + import { NumberComparator } from "@openstatus/sdk-node"; 218 + 219 + statusCodeAssertions: [ 220 + { comparator: NumberComparator.EQUAL, target: BigInt(200) }, 221 + { comparator: NumberComparator.LESS_THAN, target: BigInt(400) }, 222 + ]; 223 + ``` 224 + 225 + ### Body Assertions 226 + 227 + Validate response body content using `StringComparator`. 228 + 229 + ```typescript 230 + import { StringComparator } from "@openstatus/sdk-node"; 231 + 232 + bodyAssertions: [ 233 + { comparator: StringComparator.CONTAINS, target: '"status":"ok"' }, 234 + { comparator: StringComparator.NOT_EMPTY, target: "" }, 235 + ]; 236 + ``` 237 + 238 + ### Header Assertions 239 + 240 + Validate response headers using `StringComparator` with a header `key`. 241 + 242 + ```typescript 243 + import { StringComparator } from "@openstatus/sdk-node"; 244 + 245 + headerAssertions: [ 246 + { 247 + key: "content-type", 248 + comparator: StringComparator.CONTAINS, 249 + target: "application/json", 250 + }, 251 + ]; 252 + ``` 253 + 254 + ### DNS Record Assertions 255 + 256 + Validate DNS records using `RecordComparator`. Supported record types: `A`, `AAAA`, `CNAME`, `MX`, `TXT`. 257 + 258 + ```typescript 259 + import { RecordComparator } from "@openstatus/sdk-node"; 260 + 261 + recordAssertions: [ 262 + { 263 + record: "A", 264 + comparator: RecordComparator.EQUAL, 265 + target: "93.184.216.34", 266 + }, 267 + { 268 + record: "CNAME", 269 + comparator: RecordComparator.CONTAINS, 270 + target: "cdn", 271 + }, 272 + ]; 273 + ``` 274 + 275 + ## TypeScript Type Exports 276 + 277 + All types and enums exported from `@openstatus/sdk-node`: 278 + 279 + ### Monitor Types 280 + 281 + - `HTTPMonitor`, `Headers`, `OpenTelemetryConfig` — HTTP monitor configuration 282 + - `TCPMonitor` — TCP monitor configuration 283 + - `DNSMonitor` — DNS monitor configuration 284 + - `StatusCodeAssertion`, `BodyAssertion`, `HeaderAssertion`, `RecordAssertion` — assertion types 285 + - `CreateHTTPMonitorRequest`, `CreateHTTPMonitorResponse` — HTTP monitor CRUD 286 + - `CreateTCPMonitorRequest`, `CreateTCPMonitorResponse` — TCP monitor CRUD 287 + - `CreateDNSMonitorRequest`, `CreateDNSMonitorResponse` — DNS monitor CRUD 288 + - `UpdateHTTPMonitorRequest`, `UpdateHTTPMonitorResponse` 289 + - `UpdateTCPMonitorRequest`, `UpdateTCPMonitorResponse` 290 + - `UpdateDNSMonitorRequest`, `UpdateDNSMonitorResponse` 291 + - `ListMonitorsRequest`, `ListMonitorsResponse` 292 + - `DeleteMonitorRequest`, `DeleteMonitorResponse` 293 + - `TriggerMonitorRequest`, `TriggerMonitorResponse` 294 + - `GetMonitorStatusRequest`, `GetMonitorStatusResponse`, `RegionStatus` 295 + - `GetMonitorSummaryRequest`, `GetMonitorSummaryResponse` 296 + 297 + ### Monitor Enums 298 + 299 + - `Periodicity` — check interval 300 + - `Region` — monitoring region 301 + - `MonitorStatus` — active / degraded / error 302 + - `HTTPMethod` — HTTP methods 303 + - `TimeRange` — metrics time range 304 + - `NumberComparator`, `StringComparator`, `RecordComparator` — assertion comparators 305 + 306 + ### Health Types 307 + 308 + - `CheckRequest`, `CheckResponse` 309 + - `ServingStatus` — serving / not serving 310 + 311 + ### Status Report Types 312 + 313 + - `StatusReport`, `StatusReportSummary`, `StatusReportUpdate` 314 + - `CreateStatusReportRequest`, `CreateStatusReportResponse` 315 + - `GetStatusReportRequest`, `GetStatusReportResponse` 316 + - `ListStatusReportsRequest`, `ListStatusReportsResponse` 317 + - `UpdateStatusReportRequest`, `UpdateStatusReportResponse` 318 + - `DeleteStatusReportRequest`, `DeleteStatusReportResponse` 319 + - `AddStatusReportUpdateRequest`, `AddStatusReportUpdateResponse` 320 + - `StatusReportStatus` — investigating / identified / monitoring / resolved 321 + 322 + ### Status Page Types 323 + 324 + - `StatusPage`, `StatusPageSummary` 325 + - `PageComponent`, `PageComponentGroup` 326 + - `PageSubscriber` 327 + - `CreateStatusPageRequest`, `CreateStatusPageResponse` 328 + - `GetStatusPageRequest`, `GetStatusPageResponse` 329 + - `ListStatusPagesRequest`, `ListStatusPagesResponse` 330 + - `UpdateStatusPageRequest`, `UpdateStatusPageResponse` 331 + - `DeleteStatusPageRequest`, `DeleteStatusPageResponse` 332 + - `AddMonitorComponentRequest`, `AddMonitorComponentResponse` 333 + - `AddStaticComponentRequest`, `AddStaticComponentResponse` 334 + - `RemoveComponentRequest`, `RemoveComponentResponse` 335 + - `UpdateComponentRequest`, `UpdateComponentResponse` 336 + - `CreateComponentGroupRequest`, `CreateComponentGroupResponse` 337 + - `DeleteComponentGroupRequest`, `DeleteComponentGroupResponse` 338 + - `UpdateComponentGroupRequest`, `UpdateComponentGroupResponse` 339 + - `SubscribeToPageRequest`, `SubscribeToPageResponse` 340 + - `UnsubscribeFromPageRequest`, `UnsubscribeFromPageResponse` 341 + - `ListSubscribersRequest`, `ListSubscribersResponse` 342 + - `GetStatusPageContentRequest`, `GetStatusPageContentResponse` 343 + - `GetOverallStatusRequest`, `GetOverallStatusResponse`, `ComponentStatus` 344 + - `OverallStatus`, `PageAccessType`, `PageTheme`, `PageComponentType` 345 + 346 + ### Maintenance Types 347 + 348 + - `Maintenance`, `MaintenanceSummary` 349 + - `CreateMaintenanceRequest`, `CreateMaintenanceResponse` 350 + - `GetMaintenanceRequest`, `GetMaintenanceResponse` 351 + - `ListMaintenancesRequest`, `ListMaintenancesResponse` 352 + - `UpdateMaintenanceRequest`, `UpdateMaintenanceResponse` 353 + - `DeleteMaintenanceRequest`, `DeleteMaintenanceResponse` 354 + 355 + ### Notification Types 356 + 357 + - `Notification`, `NotificationSummary` 358 + - `NotificationData` 359 + - `DiscordData`, `EmailData`, `GoogleChatData`, `GrafanaOncallData`, `NtfyData`, `OpsgenieData`, `PagerDutyData`, `SlackData`, `SmsData`, `TelegramData`, `WebhookData`, `WebhookHeader`, `WhatsappData` 360 + - `CreateNotificationRequest`, `CreateNotificationResponse` 361 + - `GetNotificationRequest`, `GetNotificationResponse` 362 + - `ListNotificationsRequest`, `ListNotificationsResponse` 363 + - `UpdateNotificationRequest`, `UpdateNotificationResponse` 364 + - `DeleteNotificationRequest`, `DeleteNotificationResponse` 365 + - `SendTestNotificationRequest`, `SendTestNotificationResponse` 366 + - `CheckNotificationLimitRequest`, `CheckNotificationLimitResponse` 367 + - `NotificationProvider`, `OpsgenieRegion` 368 + 369 + ### Client Types 370 + 371 + - `OpenStatusClient` — client interface 372 + - `OpenStatusClientOptions` — client configuration 373 + - `createOpenStatusClient` — factory function 374 + - `openstatus` — default client instance
+223
docs/status-page-service.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Status Page Service 4 + 5 + Manage status pages, components, component groups, and subscribers. The Status Page Service provides 17 RPC methods. 6 + 7 + ## Status Page CRUD 8 + 9 + ### Create Status Page 10 + 11 + ```typescript 12 + const { statusPage } = await client.statusPage.v1.StatusPageService 13 + .createStatusPage({ 14 + title: "My Service Status", 15 + slug: "my-service", 16 + description: "Status page for My Service", 17 + homepageUrl: "https://example.com", 18 + contactUrl: "https://example.com/contact", 19 + }); 20 + 21 + console.log(`Status page created: ${statusPage?.id}`); 22 + ``` 23 + 24 + ### Get Status Page 25 + 26 + ```typescript 27 + const { statusPage } = await client.statusPage.v1.StatusPageService 28 + .getStatusPage({ id: "page_123" }); 29 + ``` 30 + 31 + ### List Status Pages 32 + 33 + ```typescript 34 + const { statusPages, totalSize } = await client.statusPage.v1.StatusPageService 35 + .listStatusPages({ limit: 10, offset: 0 }); 36 + 37 + console.log(`Found ${totalSize} status pages`); 38 + ``` 39 + 40 + ### Update Status Page 41 + 42 + ```typescript 43 + const { statusPage } = await client.statusPage.v1.StatusPageService 44 + .updateStatusPage({ 45 + id: "page_123", 46 + title: "Updated Title", 47 + description: "Updated description", 48 + }); 49 + ``` 50 + 51 + ### Delete Status Page 52 + 53 + ```typescript 54 + const { success } = await client.statusPage.v1.StatusPageService 55 + .deleteStatusPage({ id: "page_123" }); 56 + ``` 57 + 58 + ## Components 59 + 60 + Components represent individual services on a status page. They can be linked to a monitor (automatically reflects monitor status) or static (manually managed). 61 + 62 + ### Add Monitor Component 63 + 64 + ```typescript 65 + const { component } = await client.statusPage.v1.StatusPageService 66 + .addMonitorComponent({ 67 + pageId: "page_123", 68 + monitorId: "mon_456", 69 + name: "API Server", 70 + description: "Main API endpoint", 71 + order: 1, 72 + groupId: "group_789", 73 + }); 74 + ``` 75 + 76 + ### Add Static Component 77 + 78 + ```typescript 79 + const { component } = await client.statusPage.v1.StatusPageService 80 + .addStaticComponent({ 81 + pageId: "page_123", 82 + name: "Third-party Service", 83 + description: "External dependency", 84 + order: 2, 85 + }); 86 + ``` 87 + 88 + ### Update Component 89 + 90 + ```typescript 91 + const { component } = await client.statusPage.v1.StatusPageService 92 + .updateComponent({ 93 + id: "comp_123", 94 + name: "Updated Component Name", 95 + description: "Updated description", 96 + order: 3, 97 + groupId: "group_789", 98 + groupOrder: 1, 99 + }); 100 + ``` 101 + 102 + ### Remove Component 103 + 104 + ```typescript 105 + const { success } = await client.statusPage.v1.StatusPageService 106 + .removeComponent({ id: "comp_123" }); 107 + ``` 108 + 109 + ## Component Groups 110 + 111 + Group related components together on a status page. 112 + 113 + ### Create Component Group 114 + 115 + ```typescript 116 + const { group } = await client.statusPage.v1.StatusPageService 117 + .createComponentGroup({ 118 + pageId: "page_123", 119 + name: "Core Services", 120 + }); 121 + ``` 122 + 123 + ### Update Component Group 124 + 125 + ```typescript 126 + const { group } = await client.statusPage.v1.StatusPageService 127 + .updateComponentGroup({ 128 + id: "group_123", 129 + name: "Updated Group Name", 130 + }); 131 + ``` 132 + 133 + ### Delete Component Group 134 + 135 + ```typescript 136 + const { success } = await client.statusPage.v1.StatusPageService 137 + .deleteComponentGroup({ id: "group_123" }); 138 + ``` 139 + 140 + ## Subscribers 141 + 142 + Manage email subscriptions to status page updates. 143 + 144 + ### Subscribe to Page 145 + 146 + ```typescript 147 + const { subscriber } = await client.statusPage.v1.StatusPageService 148 + .subscribeToPage({ 149 + pageId: "page_123", 150 + email: "user@example.com", 151 + }); 152 + ``` 153 + 154 + ### Unsubscribe from Page 155 + 156 + Unsubscribe by email or subscriber ID using the `identifier` oneof: 157 + 158 + ```typescript 159 + // By email 160 + const { success } = await client.statusPage.v1.StatusPageService 161 + .unsubscribeFromPage({ 162 + pageId: "page_123", 163 + identifier: { case: "email", value: "user@example.com" }, 164 + }); 165 + 166 + // By subscriber ID 167 + const { success: success2 } = await client.statusPage.v1.StatusPageService 168 + .unsubscribeFromPage({ 169 + pageId: "page_123", 170 + identifier: { case: "id", value: "sub_456" }, 171 + }); 172 + ``` 173 + 174 + ### List Subscribers 175 + 176 + ```typescript 177 + const { subscribers, totalSize } = await client.statusPage.v1.StatusPageService 178 + .listSubscribers({ 179 + pageId: "page_123", 180 + limit: 50, 181 + offset: 0, 182 + includeUnsubscribed: false, 183 + }); 184 + ``` 185 + 186 + ## Get Status Page Content 187 + 188 + Get the full content of a status page including components, groups, active status reports, and maintenance windows. Identify the page by ID or slug. 189 + 190 + ```typescript 191 + const content = await client.statusPage.v1.StatusPageService 192 + .getStatusPageContent({ 193 + identifier: { case: "slug", value: "my-service" }, 194 + }); 195 + 196 + console.log(`Page: ${content.statusPage?.title}`); 197 + console.log(`Components: ${content.components.length}`); 198 + console.log(`Groups: ${content.groups.length}`); 199 + console.log(`Active reports: ${content.statusReports.length}`); 200 + console.log(`Maintenances: ${content.maintenances.length}`); 201 + ``` 202 + 203 + ## Get Overall Status 204 + 205 + Get the aggregated status of a status page and per-component statuses. 206 + 207 + ```typescript 208 + import { createOpenStatusClient, OverallStatus } from "@openstatus/sdk-node"; 209 + 210 + const client = createOpenStatusClient({ 211 + apiKey: process.env.OPENSTATUS_API_KEY, 212 + }); 213 + 214 + const { overallStatus, componentStatuses } = await client.statusPage.v1 215 + .StatusPageService.getOverallStatus({ 216 + identifier: { case: "id", value: "page_123" }, 217 + }); 218 + 219 + console.log(`Overall: ${OverallStatus[overallStatus]}`); 220 + for (const { componentId, status } of componentStatuses) { 221 + console.log(` ${componentId}: ${OverallStatus[status]}`); 222 + } 223 + ```
+103
docs/status-report-service.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # Status Report Service 4 + 5 + Manage incident reports with update timelines. The Status Report Service provides 6 RPC methods. 6 + 7 + ## Create Status Report 8 + 9 + ```typescript 10 + import { 11 + createOpenStatusClient, 12 + StatusReportStatus, 13 + } from "@openstatus/sdk-node"; 14 + 15 + const client = createOpenStatusClient({ 16 + apiKey: process.env.OPENSTATUS_API_KEY, 17 + }); 18 + 19 + const { statusReport } = await client.statusReport.v1.StatusReportService 20 + .createStatusReport({ 21 + title: "API Degradation", 22 + status: StatusReportStatus.INVESTIGATING, 23 + message: "We are investigating reports of increased latency.", 24 + date: "2024-01-15T10:30:00Z", 25 + pageId: "page_123", 26 + pageComponentIds: ["comp_456"], 27 + notify: true, 28 + }); 29 + 30 + console.log(`Status report created: ${statusReport?.id}`); 31 + ``` 32 + 33 + ## Add Status Report Update 34 + 35 + Add a new entry to a status report's timeline. 36 + 37 + ```typescript 38 + import { StatusReportStatus } from "@openstatus/sdk-node"; 39 + 40 + const { statusReport } = await client.statusReport.v1.StatusReportService 41 + .addStatusReportUpdate({ 42 + statusReportId: "sr_123", 43 + status: StatusReportStatus.IDENTIFIED, 44 + message: "The issue has been identified as a database connection problem.", 45 + date: "2024-01-15T11:00:00Z", 46 + notify: true, 47 + }); 48 + ``` 49 + 50 + ## List Status Reports 51 + 52 + List status reports with optional status filtering and pagination. 53 + 54 + ```typescript 55 + import { StatusReportStatus } from "@openstatus/sdk-node"; 56 + 57 + const { statusReports, totalSize } = await client.statusReport.v1 58 + .StatusReportService.listStatusReports({ 59 + limit: 10, 60 + offset: 0, 61 + statuses: [StatusReportStatus.INVESTIGATING, StatusReportStatus.IDENTIFIED], 62 + }); 63 + 64 + console.log(`Found ${totalSize} status reports`); 65 + ``` 66 + 67 + ## Get / Update / Delete Status Reports 68 + 69 + ### Get Status Report 70 + 71 + Returns the full report including the updates timeline. 72 + 73 + ```typescript 74 + import { StatusReportStatus } from "@openstatus/sdk-node"; 75 + 76 + const { statusReport } = await client.statusReport.v1.StatusReportService 77 + .getStatusReport({ id: "sr_123" }); 78 + 79 + console.log(`Title: ${statusReport?.title}`); 80 + console.log(`Status: ${StatusReportStatus[statusReport?.status ?? 0]}`); 81 + 82 + for (const update of statusReport?.updates ?? []) { 83 + console.log(` ${update.date}: [${StatusReportStatus[update.status]}] ${update.message}`); 84 + } 85 + ``` 86 + 87 + ### Update Status Report 88 + 89 + ```typescript 90 + const { statusReport } = await client.statusReport.v1.StatusReportService 91 + .updateStatusReport({ 92 + id: "sr_123", 93 + title: "Updated Title", 94 + pageComponentIds: ["comp_456", "comp_789"], 95 + }); 96 + ``` 97 + 98 + ### Delete Status Report 99 + 100 + ```typescript 101 + const { success } = await client.statusReport.v1.StatusReportService 102 + .deleteStatusReport({ id: "sr_123" }); 103 + ```
+153
docs/typescript-tips.md
··· 1 + [← Back to index](./index.md) 2 + 3 + # TypeScript Tips 4 + 5 + ## Working with bigint Fields 6 + 7 + Protocol Buffers `int64` fields map to `bigint` in TypeScript. This affects: 8 + 9 + - **Monitor configuration**: `timeout`, `retry`, `degradedAt` 10 + - **Assertions**: `StatusCodeAssertion.target` 11 + - **Monitor summary**: `totalSuccessful`, `totalDegraded`, `totalFailed`, `p50`, `p75`, `p90`, `p95`, `p99` 12 + 13 + Use `BigInt()` to create values: 14 + 15 + ```typescript 16 + const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({ 17 + monitor: { 18 + name: "My API", 19 + url: "https://example.com", 20 + periodicity: Periodicity.PERIODICITY_1M, 21 + active: true, 22 + timeout: BigInt(30000), // 30 seconds 23 + retry: BigInt(5), // 5 retries 24 + degradedAt: BigInt(3000), // degraded after 3s 25 + statusCodeAssertions: [ 26 + { comparator: NumberComparator.EQUAL, target: BigInt(200) }, 27 + ], 28 + }, 29 + }); 30 + ``` 31 + 32 + Reading bigint values: 33 + 34 + ```typescript 35 + const summary = await client.monitor.v1.MonitorService.getMonitorSummary({ 36 + id: "mon_123", 37 + timeRange: TimeRange.TIME_RANGE_7D, 38 + regions: [], 39 + }); 40 + 41 + // bigint values — use Number() for display if values are safe 42 + console.log(`P95 latency: ${summary.p95}ms`); 43 + console.log(`Total checks: ${summary.totalSuccessful + summary.totalDegraded + summary.totalFailed}`); 44 + ``` 45 + 46 + ## Handling oneof Types 47 + 48 + Several responses use protobuf `oneof` fields, which map to discriminated unions in TypeScript. 49 + 50 + ### MonitorConfig (getMonitor) 51 + 52 + ```typescript 53 + const { monitor } = await client.monitor.v1.MonitorService.getMonitor({ 54 + id: "mon_123", 55 + }); 56 + 57 + switch (monitor?.config.case) { 58 + case "http": 59 + // monitor.config.value is HTTPMonitor 60 + console.log(`URL: ${monitor.config.value.url}`); 61 + break; 62 + case "tcp": 63 + // monitor.config.value is TCPMonitor 64 + console.log(`URI: ${monitor.config.value.uri}`); 65 + break; 66 + case "dns": 67 + // monitor.config.value is DNSMonitor 68 + console.log(`Domain: ${monitor.config.value.uri}`); 69 + break; 70 + } 71 + ``` 72 + 73 + ### NotificationData (createNotification) 74 + 75 + The `data.data` field selects the provider-specific configuration: 76 + 77 + ```typescript 78 + // The case string matches the provider in camelCase 79 + data: { 80 + data: { case: "slack", value: { webhookUrl: "..." } } 81 + } 82 + data: { 83 + data: { case: "googleChat", value: { webhookUrl: "..." } } 84 + } 85 + data: { 86 + data: { case: "grafanaOncall", value: { webhookUrl: "..." } } 87 + } 88 + ``` 89 + 90 + ### Status Page Identifiers 91 + 92 + `getStatusPageContent` and `getOverallStatus` accept a page identifier by ID or slug: 93 + 94 + ```typescript 95 + // By ID 96 + { identifier: { case: "id", value: "page_123" } } 97 + 98 + // By slug 99 + { identifier: { case: "slug", value: "my-service" } } 100 + ``` 101 + 102 + ### Unsubscribe Identifier 103 + 104 + `unsubscribeFromPage` accepts an email or subscriber ID: 105 + 106 + ```typescript 107 + // By email 108 + { identifier: { case: "email", value: "user@example.com" } } 109 + 110 + // By subscriber ID 111 + { identifier: { case: "id", value: "sub_456" } } 112 + ``` 113 + 114 + ## Migrating from Default Client to createOpenStatusClient 115 + 116 + **Before** — manual headers on every call: 117 + 118 + ```typescript 119 + import { openstatus } from "@openstatus/sdk-node"; 120 + 121 + const headers = { "x-openstatus-key": process.env.OPENSTATUS_API_KEY }; 122 + 123 + const { httpMonitors } = await openstatus.monitor.v1.MonitorService 124 + .listMonitors({}, { headers }); 125 + 126 + const { monitor } = await openstatus.monitor.v1.MonitorService 127 + .createHTTPMonitor({ 128 + monitor: { name: "API", url: "https://example.com", periodicity: 2, active: true }, 129 + }, { headers }); 130 + ``` 131 + 132 + **After** — configure once, use everywhere: 133 + 134 + ```typescript 135 + import { createOpenStatusClient, Periodicity } from "@openstatus/sdk-node"; 136 + 137 + const client = createOpenStatusClient({ 138 + apiKey: process.env.OPENSTATUS_API_KEY, 139 + }); 140 + 141 + const { httpMonitors } = await client.monitor.v1.MonitorService 142 + .listMonitors({}); 143 + 144 + const { monitor } = await client.monitor.v1.MonitorService 145 + .createHTTPMonitor({ 146 + monitor: { 147 + name: "API", 148 + url: "https://example.com", 149 + periodicity: Periodicity.PERIODICITY_1M, 150 + active: true, 151 + }, 152 + }); 153 + ```
+2 -2
src/mod.ts
··· 32 32 * ```typescript 33 33 * import { openstatus, Periodicity } from "@openstatus/sdk-node"; 34 34 * 35 - * const headers = { "x-openstatus-key": `Bearer ${process.env.OPENSTATUS_API_KEY}` }; 35 + * const headers = { "x-openstatus-key": `${process.env.OPENSTATUS_API_KEY}` }; 36 36 * const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor({ 37 37 * monitor: { name: "My API", url: "https://api.example.com", periodicity: Periodicity.PERIODICITY_1M, active: true }, 38 38 * }, { headers }); ··· 543 543 * ```typescript 544 544 * import { openstatus, Periodicity } from "@openstatus/sdk-node"; 545 545 * 546 - * const headers = { "x-openstatus-key": `Bearer ${process.env.OPENSTATUS_API_KEY}` }; 546 + * const headers = { "x-openstatus-key": `${process.env.OPENSTATUS_API_KEY}` }; 547 547 * const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor({ 548 548 * monitor: { name: "My Website", url: "https://example.com", periodicity: Periodicity.PERIODICITY_1M, active: true }, 549 549 * }, { headers });