---
title: "Vendor status page watch | Grafana Cloud documentation"
description: "Watch a vendor's public status page and post to Slack when they open a new incident, so you hear about upstream outages before your users do."
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Vendor status page watch

> Note
> 
> Grafana Workflows is currently in [public preview](https://grafana.com/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.

Watch a vendor’s public status page and post to Slack when they open a new incident, so you hear about upstream outages before your users do.

This Grafana Workflows blueprint is in the **Integrations** category of the Blueprints library.

## Before you begin

To use this blueprint, you need:

- Slack connected to Grafana IRM. For details, refer to [Configure Slack for Grafana IRM](https://grafana.com/docs/grafana-cloud/alerting-and-irm/irm/integrations/chat-and-collaboration/slack/).

## Steps

Steps run in order from first to last. A step inside a switch branch runs only when Workflows chooses that branch.

Expand table

| Step                                   | ID                | Type                 | Description                                                                                                                                                                                                                |
|----------------------------------------|-------------------|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Fetch unresolved vendor incidents      | `fetch-incidents` | `http.call`          | Reads the vendor’s unresolved incidents from the public Statuspage API. It defaults to GitHub. To watch another vendor, replace `www.githubstatus.com` with their Statuspage host, for example `www.cloudflarestatus.com`. |
| Fail if the status page is unreachable | `check-response`  | `filter`             | Fails the run when the status page does not respond with 200, so you can spot a broken URL. No changes needed.                                                                                                             |
| Find newly opened incidents            | `find-new`        | `code.execute`       | Keeps incidents opened since the previous run. Keep `windowMinutes` equal to the schedule interval.                                                                                                                        |
| Anything new?                          | `anything-new`    | `filter`             | Stops quiet runs without posting. No changes needed.                                                                                                                                                                       |
| Post to Slack                          | `notify`          | `slack.message.post` | Posts the new vendor incidents. Set `channelID` to the channel where you track upstream dependencies.                                                                                                                      |

For the inputs and outputs of each step type, refer to [Step and trigger types reference](https://grafana.com/docs/grafana-cloud/platform/workflows/reference/step-trigger-types).

Before you turn on the workflow, customize any steps that need input from you, such as a channel ID or a schedule name. Each step’s description says what to set.

## Workflow definition

Save this definition as a YAML file to create the workflow with gcx, the Workflows API, or Terraform, or give it to a coding agent as an example. Replace *FOLDER\_UID* with the UID of the folder for the workflow. Blueprints start disabled, so finish customizing the steps before you set `enabled` to `true`. For details, refer to [Manage workflows as code](https://grafana.com/docs/grafana-cloud/platform/workflows/as-code).

YAML ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```yaml
apiVersion: workflows.ext.grafana.app/v1alpha1
kind: Definition
metadata:
  name: vendor-status-page-watch
  annotations:
    grafana.app/folder: <FOLDER_UID>
spec:
  name: Vendor status page watch
  enabled: false
  startWhen:
    matchingRules: []
    schedules:
      - '*/10 * * * *'
  steps:
    - id: fetch-incidents
      type: http.call
      name: Fetch unresolved vendor incidents
      description: >-
        Reads the vendor's unresolved incidents from the public Statuspage API. It defaults to
        GitHub. To watch another vendor, replace www.githubstatus.com with their Statuspage host, for
        example www.cloudflarestatus.com.
      inputs:
        method: 'GET'
        url: 'https://www.githubstatus.com/api/v2/incidents/unresolved.json'
    - id: check-response
      type: filter
      name: Fail if the status page is unreachable
      description: Fails the run when the status page does not respond with 200, so you can spot a broken URL. No changes needed.
      inputs:
        condition: "steps['fetch-incidents'].outputs.responseCode == 200"
        failOnExit: 'true'
    - id: find-new
      type: code.execute
      name: Find newly opened incidents
      description: Keeps incidents opened since the previous run. Keep windowMinutes equal to the schedule interval.
      inputs:
        language: 'python'
        args: '{"windowMinutes": 10}'
        code: |
          import json
          from datetime import datetime, timedelta, timezone

          body = json.loads(context["steps"]["fetch-incidents"]["outputs"]["responseBody"])
          cutoff = datetime.now(timezone.utc) - timedelta(minutes=args.get("windowMinutes", 10))
          vendor = body.get("page", {}).get("name", "Vendor")

          new = []
          for incident in body.get("incidents", []):
              created = datetime.fromisoformat(incident["created_at"].replace("Z", "+00:00"))
              if created >= cutoff:
                  new.append(incident)

          lines = [
              f"• <{i.get('shortlink') or body.get('page', {}).get('url', '')}|{i['name']}> (impact: {i.get('impact', 'unknown')}, status: {i.get('status', 'unknown')})"
              for i in new
          ]
          print(json.dumps({
              "count": len(new),
              "message": f":satellite: *{vendor}* reported a new incident:\n" + "\n".join(lines),
          }))
    - id: anything-new
      type: filter
      name: Anything new?
      description: Stops quiet runs without posting. No changes needed.
      inputs:
        condition: "json_parse(steps['find-new'].outputs.stdout).count > 0"
    - id: notify
      type: slack.message.post
      name: Post to Slack
      description: Posts the new vendor incidents. Set channelID to the channel where you track upstream dependencies.
      inputs:
        channelID: ''
        messageText: "${json_parse(steps['find-new'].outputs.stdout).message}"
```

## How it works

This section explains when the workflow runs and how its steps work together.

### When it runs

This blueprint runs on the schedule `*/10 * * * *`.

### How the steps fit together

These notes cover how the steps connect and which Workflows behaviors the blueprint relies on.

- Runs every 10 minutes and works with any Atlassian Statuspage site.
- It defaults to GitHub’s status page, so it runs with no credentials.
- `http.call` GETs `/api/v2/incidents/unresolved.json`.
- The Python `code.execute` step parses the body, keeps incidents created within the last `windowMinutes`, and prints JSON with the new incidents and a ready-to-post message.
- Set `windowMinutes` in args to match the schedule interval, so each vendor incident is reported once.
- Scheduled workflows cannot use `runOnceFor`, so the time window is the deduplication.
- A filter stops quiet runs, and a filter with `failOnExit` makes HTTP errors visible as failed runs.
- Customize the status page host in the URL, the schedule, `windowMinutes`, and the Slack channel.
- Copy the workflow once per vendor you depend on.

## Next steps

- [Blueprints](https://grafana.com/docs/grafana-cloud/platform/workflows/reference/blueprints)
- [Start from a blueprint](https://grafana.com/docs/grafana-cloud/platform/workflows/build/use-blueprints)
- [Manage workflows as code](https://grafana.com/docs/grafana-cloud/platform/workflows/as-code)
- [Step and trigger types reference](https://grafana.com/docs/grafana-cloud/platform/workflows/reference/step-trigger-types)
