Public preview Grafana Cloud
Last reviewed: November 9, 2026

Vendor status page watch

Note

Grafana Workflows is currently in public preview. 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:

Steps

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

StepIDTypeDescription
Fetch unresolved vendor incidentsfetch-incidentshttp.callReads 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 unreachablecheck-responsefilterFails the run when the status page does not respond with 200, so you can spot a broken URL. No changes needed.
Find newly opened incidentsfind-newcode.executeKeeps incidents opened since the previous run. Keep windowMinutes equal to the schedule interval.
Anything new?anything-newfilterStops quiet runs without posting. No changes needed.
Post to Slacknotifyslack.message.postPosts 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.

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.

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