···8787 };
8888};
8989```
9090+9191+You can use it to check from a region the following metrics:
9292+9393+- DNS Look up time,
9494+- TLS handshake time,
9595+- TCP connection time,
9696+- Time to first byte.
···11+---
22+title: Cron Monitor
33+description: "How to create your first cron monitor with OpenStatus.dev"
44+---
55+66+## What is a Cron Monitor? ๐ค
77+88+A cron monitor allows you to monitor your cron jobs. You call your OpenStatus
99+endpoint at the end of your cron job. If we haven't received your call we will
1010+trigger an alert and notify you.
1111+1212+## Configure your cron monitor ๐
1313+1414+๐ง Coming soon ๐ง
+23
apps/docs/features/incident.mdx
···11+---
22+title: Incident
33+description: "How incident are created, how to acknowledge, and resolve them๐ฅ"
44+---
55+66+## What is an incident ๐งโ๐ซ
77+88+We automatically create an incident when we detect a problem with your service.
99+When a monitor fails in more than 50% of the locations, we create an incident.
1010+We do that in order to avoid false positives.
1111+1212+## How to acknowledge an incident
1313+1414+Go to the incident page and click on the acknowledge button.
1515+1616+## How to resolve an incident
1717+1818+Go to the incident page and click on the resolve button.
1919+2020+## Auto resolve an incident ๐
2121+2222+We automatically resolve an incident when the monitor is passing in more than
2323+50% of the locations.
+32
apps/docs/features/notification.mdx
···11+---
22+title: Overview
33+description: "How to create your first alert with OpenStatus.dev"
44+---
55+66+If you connect notification channels to your OpenStatus account, you can receive
77+alerts when your services are down. We will contact you when an incident is
88+created.
99+1010+<Frame caption="Create your notification channel">
1111+ <img
1212+ src="/images/notification/discord-notification.png"
1313+ alt="Create your notification bot"
1414+ />
1515+</Frame>
1616+1717+## Notification channels
1818+1919+<CardGroup cols={2}>
2020+ <Card title="Email โ๏ธ" href="/features/notification/email">
2121+ Receive an email
2222+ </Card>
2323+ <Card title="Slack ๐ฃ" href="/features/notification/slack">
2424+ Get notified on Slack
2525+ </Card>
2626+ <Card title="Discord ๐ค" href="/features/notification/discord">
2727+ Get notified on Discord
2828+ </Card>
2929+ <Card title="SMS ๐ฑ" href="/features/notification/sms">
3030+ Receive a text message
3131+ </Card>
3232+</CardGroup>
+5
apps/docs/features/notification/email.mdx
···11+---
22+title: Email
33+---
44+55+When we create an incident we send an email to the email provided.
+6
apps/docs/features/notification/sms.mdx
···11+---
22+title: SMS
33+---
44+55+When you subscribe to a paid plan you can receive SMS notifications when your
66+monitor is down.
+6
apps/docs/features/status-page-subscribers.mdx
···11+---
22+title: Status Page Subscribers
33+---
44+55+If you are on a paid plan. Your status page will have a subscribers section.
66+This section will allow your users to subscribe to your status page update.
-14
apps/docs/getting-started/heartbeat.mdx
···11----
22-title: Heartbeat
33-description: "How to create your first heartbeat with OpenStatus.dev"
44----
55-66-## What is a heartbeat? ๐
77-88-A heartbeat allows you to monitor your cron jobs. You call your OpenStatus
99-endpoint at the end of your cron job. If we haven't received your call we will
1010-trigger an alert and notify you.
1111-1212-## Configure your heartbeat ๐
1313-1414-๐ง Coming soon ๐ง
-13
apps/docs/getting-started/incident.mdx
···11----
22-title: Incident
33-description: "How to create your first incident ๐ฅ"
44----
55-66-<Warning>
77- **Incidents** have been renamed to [Status
88- Reports](/getting-started/status-report). That also includes the [API
99- endpoint](/api-reference/status_report). It will allow us to differenciate
1010- between **public status reports** and **internal incident management**.
1111-</Warning>
1212-1313-Coming soon: Internal Incident Management
···1515- a **name** to identify your monitor
1616- the **URL** to checked
17171818-We will store the **response time** and the **status code** of your endpoint.
1818+We will store the **response time**, the **status code**, the **headers**
1919+returned, and the **timing metrics** of your endpoint.
19202021<Frame caption="Monitor your endpoint">
2122 <img
···33343435Add custom key-value **HTTP Headers** to your request.
35363636-> OpenStatus automatically appends the `"OpenStatus-Ping": "true"` header to
3737+> OpenStatus automatically set the `"User-Agent": "OpenStatus/1.0"` header to
3738> your request. This header is used to identify the request as a ping request
3839> and can be exluded from your analytics.
39404041If you select the `POST` method, you can add a custom **HTTP Body** to your
4142request.
42434343-### Advanced Configuration โฑ๏ธ
4444+### Advanced Configuration โ๏ธ
44454545-Define the **frequency** of your checks. You can choose between: `1m`, `5m`,
4646-`10m` (default), `30min` or `1h`.
4646+You can pause your monitor with the **active** switch button.
47474848-By default, **all regions** are enabled. You can disable some regions if you
4949-want to. Leaving it empty will check your endpoint from a random region.
4848+#### Frequency โฑ
50495151-The **description** is optional. If defined, an `Info` tooltip will be added to
5252-your monitor name.
5050+Define the **frequency** of your checks. You can choose between: `30s`, `1m`,
5151+`5m`, `10m` (default), `30min` or `1h`.
53525454-You can always pause your monitor with the **active** switch button.
5353+#### Regions ๐
55545656-### Notifications ๐
5555+By default, **all regions** are enabled. You can disable some regions if you
5656+want to. Our regions are:
57575858-Get informed whenever a check fails. You can add multiple notification channels.
5858+- `ams` - Amsterdam, Netherlands - ๐ณ๐ฑ
5959+- `iad` - Ashburn, Virginia, USA - ๐บ๐ธ
6060+- `jnb` - Johannesburg, South Africa - ๐ฟ๐ฆ
6161+- `hkg` - Hong Kong, Honkg Kong - ๐ญ๐ฐ
6262+- `gru` - Sao Paulo, Brazil - ๐ง๐ท
6363+- `syd` - Sydney, Australia - ๐ฆ๐บ
59646060-We send a webhook to Slack or Discord channels. Or you can also receive an
6161-email.
6565+#### Description ๐
62666363----
6767+The **description** is optional. If defined, an `Info` tooltip will be added to
6868+your monitor name.
64696565-> Create an API key and use it in your HTTP Headers to create your monitor
6666-> programmatically API.
7070+#### Timeout โณ
7171+7272+You can define a **timeout** for your request. The default value is `30s`.
-33
apps/docs/getting-started/notification.mdx
···11----
22-title: Notification
33-description: "How to create your first alert with OpenStatus.dev"
44----
55-66-You get notified when your monitor has failed. Configure multiple alerts for
77-each monitor.
88-99-We support the following notification channels: **email**, **slack** and
1010-**discord**.
1111-1212-<Frame caption="Create your notification channel">
1313- <img
1414- src="/images/notification/discord-notification.png"
1515- alt="Create your notification bot"
1616- />
1717-</Frame>
1818-1919-### Email โ๏ธ
2020-2121-Enter your email address in the alert configuration.
2222-2323-### Slack ๐ฃ
2424-2525-Create an [incoming webhook](https://api.slack.com/messaging/webhooks) in your
2626-Slack workspace. Copy the webhook URL and paste it in the alert configuration.
2727-2828-### Discord ๐ค
2929-3030-Create a
3131-[webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks)
3232-in your Discord server. Copy the webhook URL and paste it in the alert
3333-configuration.
···11----
22-title: Incident Automation
33-description: "How to use incident automation"
44----
55-66-# What is incident automation? ๐ค
77-88-When you have an incident, you might need to perform a series of actions to
99-handle it. For example, you might need to:
1010-1111-- create a slack channel
1212-- create a google meet meeting
1313-- create a Linear ticket
1414-- Perform a checklist of actions
1515-1616-Incident automation allows you to automate these actions.
1717-1818-## How to define an incident automation? ๐ค
1919-2020-Incident automation is defined in a YAML file.
···2121 the app
2222- **Self-hosting**: if you want greater control over your data and want to run
2323 the app on your own server
2424-2525-## Start with OpenStatus
2626-2727-<CardGroup cols={2}>
2828- <Card title="Monitor" href="/getting-started/monitor">
2929- Learn how to create your first monitor
3030- </Card>
3131- <Card title="Status Page" href="/getting-started/status-page">
3232- Learn how to set up your status page
3333- </Card>
3434- <Card title="Notification" href="/getting-started/notification">
3535- Learn how to set up alerting for your monitors
3636- </Card>
3737- <Card title="Incident" href="/getting-started/incident">
3838- Learn how to create your first incident
3939- </Card>
4040-</CardGroup>
···11+---
22+title: Public Status Widget
33+description: "How to add a public status widget to your website."
44+---
55+66+We have added a public endpoint where you can access the status of your status
77+page. To access it, you only need the unique `:slug` you have chosen for your
88+page.
99+1010+```bash
1111+curl https://api.openstatus.dev/public/status/:slug
1212+```
1313+1414+<Callout type="info">
1515+ We have released an `@openstatus/react` npm package that allows you to easily
1616+ integrate the pre-typed status into your React projects or use the default
1717+ widget. Read more [here](/packages/react).
1818+</Callout>
1919+2020+The response is a JSON object with the following structure:
2121+2222+```json
2323+{ "status": "operational" }
2424+```
2525+2626+in which the status can be one of the following values:
2727+2828+```ts
2929+enum Status {
3030+ Operational = "operational",
3131+ DegradedPerformance = "degraded_performance",
3232+ PartialOutage = "partial_outage",
3333+ MajorOutage = "major_outage",
3434+ UnderMaintenance = "under_maintenance", // currently not in use
3535+ Unknown = "unknown",
3636+ Incident = "incident",
3737+}
3838+```
3939+4040+### How does it work?
4141+4242+The status is calculated by the ratio `uptime / (uptime + downtime)` of the last
4343+5 cron jobs of each monitor which we accumulate together. It is a simple
4444+calculation that gives us a good overview of the status of your services.
4545+4646+```ts
4747+function getStatus(ratio: number) {
4848+ if (isNaN(ratio)) return Status.Unknown;
4949+ if (ratio >= 0.98) return Status.Operational;
5050+ if (ratio >= 0.6) return Status.DegradedPerformance;
5151+ if (ratio >= 0.3) return Status.PartialOutage;
5252+ if (ratio >= 0) return Status.MajorOutage;
5353+ return Status.Unknown;
5454+}
5555+```
5656+5757+We are caching the result for `30 seconds` to reduce the load on our database.
5858+5959+The `Status.Incident` will always be returned when then status of any incident
6060+on your page is **not** _"monitoring"_ or _"resolved"_. You can attach an
6161+incident to a monitor (implicit) or a page (explicit).
6262+6363+> If you have a doubt about the above calculation, feel free to contact us via
6464+> [ping@openstatus.dev](mailto:ping@openstatus.dev) or
6565+> [discord](https://openstatus.dev/discord).
6666+6767+### React Widget
6868+6969+We currently do not provide any SDK or package to integrate the status into your
7070+stack. But will in the future.
7171+7272+If you are using Nextjs and RSC with the `/app` directory, feel free to use that
7373+Component. Small reminder that we are using shadcn ui and tailwindcss. You might
7474+want to update the `bg-muted` and `text-foreground` classes to your needs.
7575+7676+
7777+7878+We are using `zod` to validate the response. You can use any other library if
7979+you want or just remove it. But better be safe than sorry.
8080+8181+```tsx
8282+import * as z from "zod";
8383+8484+const statusEnum = z.enum([
8585+ "operational",
8686+ "degraded_performance",
8787+ "partial_outage",
8888+ "major_outage",
8989+ "under_maintenance",
9090+ "unknown",
9191+ "incident",
9292+]);
9393+9494+const statusSchema = z.object({ status: statusEnum });
9595+9696+const dictionary = {
9797+ operational: {
9898+ label: "Operational",
9999+ color: "bg-green-500",
100100+ },
101101+ degraded_performance: {
102102+ label: "Degraded Performance",
103103+ color: "bg-yellow-500",
104104+ },
105105+ partial_outage: {
106106+ label: "Partial Outage",
107107+ color: "bg-yellow-500",
108108+ },
109109+ major_outage: {
110110+ label: "Major Outage",
111111+ color: "bg-red-500",
112112+ },
113113+ unknown: {
114114+ label: "Unknown",
115115+ color: "bg-gray-500",
116116+ },
117117+ incident: {
118118+ label: "Incident",
119119+ color: "bg-yellow-500",
120120+ },
121121+ under_maintenance: {
122122+ label: "Under Maintenance",
123123+ color: "bg-gray-500",
124124+ },
125125+} as const;
126126+127127+export async function StatusWidget({ slug }: { slug: string }) {
128128+ const res = await fetch(`https://api.openstatus.dev/public/status/${slug}`, {
129129+ next: { revalidate: 60 }, // cache request for 60 seconds
130130+ });
131131+ const data = await res.json();
132132+ const parsed = statusSchema.safeParse(data);
133133+134134+ if (!parsed.success) {
135135+ return null;
136136+ }
137137+138138+ const key = parsed.data.status;
139139+ const { label, color } = dictionary[key];
140140+141141+ return (
142142+ <a
143143+ className="border-border text-foreground/70 hover:bg-muted hover:text-foreground inline-flex max-w-fit items-center gap-2 rounded-md border px-3 py-1 text-sm"
144144+ href={`https://${slug}.openstatus.dev`}
145145+ target="_blank"
146146+ rel="noreferrer"
147147+ >
148148+ {label}
149149+ <span className="relative flex h-2 w-2">
150150+ {parsed.data.status === "operational" ? (
151151+ <span
152152+ className={`absolute inline-flex h-full w-full animate-ping rounded-full ${color} opacity-75 duration-1000`}
153153+ />
154154+ ) : null}
155155+ <span
156156+ className={`relative inline-flex h-2 w-2 rounded-full ${color}`}
157157+ />
158158+ </span>
159159+ </a>
160160+ );
161161+}
162162+```