DocsGetting StartedGetting Started
5 minUpdated 2026-09-16

Getting Started

Copy-paste your way from zero to a monitored endpoint with alerts and a status page — dashboard, CLI, API, or Terraform.

Everything on this page is copy-pasteable and verified against the current

product. Pick your path: the dashboard, the CLI, the REST API, or Terraform —

they all converge on the same monitors.

1. Get access

Dashboard: sign in at steadystack.dev — the free

tier includes 50 monitors with 3-minute checks.

CLI: install and authenticate with an API key

(Workspace Settings → API Keys, format pg_live_…):

BASH
bun add -g @steadystack/cli   # or: npm install -g @steadystack/cli

pulse auth login --key pg_live_xxxxxxxxxxxxxxxx
pulse auth status             # verify

Self-hosted? Add --url https://your-instance.example.com to auth login.

2. Create your first monitor

Dashboard: Dashboard → Monitors → New Monitor.

CLI (declarative — recommended):

BASH
cat > steadystack.yaml <<'EOF'
monitors:
  - name: marketing-site
    url: https://example.com
    interval: 60

  - name: api-health
    url: https://api.example.com/health
    interval: 30
    expectation:
      statusCode: 200
      maxResponseTime: 2000
    tags: [production]
EOF

pulse monitors apply -f steadystack.yaml

Apply is idempotent — matched by name, so re-running updates instead of

duplicating. Preview first with pulse monitors diff -f steadystack.yaml.

Full schema: Monitoring as Code.

REST API:

BASH
curl -X POST "https://app.steadystack.dev/api/v1/monitors" \
  -H "Authorization: Bearer pg_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "api-health",
    "url": "https://api.example.com/health",
    "interval": 30,
    "expectation": { "statusCode": 200 }
  }'

Terraform:

HCL
resource "steadystack_monitor" "api" {
  name     = "api-health"
  url      = "https://api.example.com/health"
  type     = "HTTP"
  interval = 30
  check_regions = ["wnam", "weur", "apac"]
}

3. Watch it check in

BASH
# Table of all monitors with live status
pulse monitors list

# Details + recent events for one monitor
pulse monitors get <monitor-id>

# Force an immediate check (exits 1 if DOWN — CI-friendly smoke test)
pulse trigger <monitor-id>

# Stream events like tail -f
pulse logs tail <monitor-id>

A monitor is UP only when a quorum of regions agrees — see

Quorum Consensus for why this eliminates

false-positive 3 AM pages.

4. Add an alert channel

Dashboard: Alerts → Notification Channels → Add Channel (Slack, Discord,

PagerDuty, Opsgenie, Email — each with a Send Test button), then

Alerts → Alert Rules → New Rule to attach it to a monitor with a trigger

(STATUS_CHANGE, LATENCY, SSL_EXPIRY, DNS_WATCHDOG, DOMAIN_EXPIRY).

Step-by-step for every channel type: Alert Channels Setup.

REST API:

BASH
# 1. Create a Slack channel
curl -X POST "https://app.steadystack.dev/api/v1/alert-channels" \
  -H "Authorization: Bearer pg_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "oncall-slack",
    "type": "SLACK",
    "config": { "webhookUrl": "https://hooks.slack.com/services/T000/B000/xxxx" }
  }'

# 2. Wire it to the monitor
curl -X POST "https://app.steadystack.dev/api/v1/alert-rules" \
  -H "Authorization: Bearer pg_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "monitorId": "<monitor-id>",
    "trigger": "STATUS_CHANGE",
    "targetStatus": "DOWN",
    "channelIds": ["<channel-id>"]
  }'

<Check>

No alert rules on a monitor? Status changes still email the workspace owner —

you're never silently unmonitored.

</Check>

5. Publish a status page

Dashboard: Status Pages → New Page, pick a slug, add monitors. Full

customization (themes, custom domain, password protection):

Customizing Status Pages.

For a custom domain, add a CNAME record pointing at cname.vercel-dns.com

(the dashboard's domain settings show the exact record) — TLS is issued

automatically.

6. Wire a CI/CD gate

Block deployments until production is verified healthy:

YAML
# GitHub Actions
- name: Deploy
  run: ./deploy.sh

- name: Wait for production to be healthy
  run: pulse wait "$MONITOR_ID" --timeout 300
  env:
    MONITOR_ID: ${{ vars.PROD_HEALTH_MONITOR_ID }}

wait exits 1 on timeout, failing the job. A dedicated health-endpoint

monitor plus this step catches broken deploys before your users do — see

GitHub Actions Gates.

What's next

GoalDoc
Assert on response bodies, JSON paths, latencyResponse Assertions
All CLI commands and flagsCLI Reference
Monitor internal/VPC endpointsDeploying Private Probes
Understand the SLA numberSLA Calculation Methodology
Invite your team with rolesTeams & RBAC
Full APIREST API Reference · Interactive explorer