# Happy Uptime API Docs

Happy Uptime exposes a JSON REST API for monitors, incidents, status pages, alerts, and analytics.

## Machine-readable endpoints
- OpenAPI: https://happyuptime.com/openapi.json
- llms.txt: https://happyuptime.com/llms.txt
- llms-full.txt: https://happyuptime.com/llms-full.txt

## Quick Start (CLI)

```bash
npm i -g happyuptime-cli
happy login          # Opens browser for authentication
happy monitors create --name "My App" --url https://myapp.com --interval 60
```

The CLI uses a device authorization flow — `happy login` opens your browser, you sign in, and the CLI receives an API key automatically. For CI/CD, use `happy login --api-key hu_xxx` with a pre-created key.

## Base URL
`https://happyuptime.com/api/v1`

## Authentication
Send your API key in the Authorization header:

```bash
curl -H "Authorization: Bearer hu_your_api_key" https://happyuptime.com/api/v1/monitors
```

Only this header format is supported. Do not use `X-API-Key`, Basic auth, or a raw token without the `Bearer` prefix.

All endpoints return JSON. Write operations require a key with at least `write` scope.

## Agent Bootstrap (No Auth Required)

AI agents can create a Happy Uptime account from scratch — no existing signup or API key needed.

- `POST /agent/bootstrap` — create account + org + project + API key from an email address. Rate-limited to 3/hr per IP. Returns `{ api_key, organization_id, claim_url }`. The API key works immediately.
- `POST /agent/invite` — invite a user to the current project (requires admin API key). Creates an account if the user doesn't exist yet. Returns a `claim_url` for new users.

The `claim_url` lets the user set their password and access the dashboard. It expires in 72 hours.

## Core resources

### Project
- `GET /project` get current project info, plan, resource limits, embed URLs, canonical public status-page URLs, badge snippets, and status pages

### Monitors
- `GET /monitors` list monitors
- `POST /monitors` create a monitor
- `GET /monitors/:id` get one monitor
- `PUT /monitors/:id` update a monitor
- `DELETE /monitors/:id` delete a monitor
- `POST /monitors/:id/pause` pause monitoring
- `POST /monitors/:id/resume` resume monitoring
- `GET /monitors/:id/checks` fetch check history
- `GET /monitors/:id/uptime` fetch uptime data
- `POST /monitors/bulk` bulk create monitors (max 50)

### Incidents
- `GET /incidents` list incidents
- `POST /incidents` create an incident
- `GET /incidents/:id` get incident details
- `PUT /incidents/:id` update incident metadata
- `POST /incidents/:id/updates` append an incident update
- `POST /incidents/:id/resolve` resolve an incident
- `DELETE /incidents/:id` delete an incident

### Status pages
- `GET /status-pages` list status pages
- `POST /status-pages` create a status page
- `GET /status-pages/:id` get a status page
- `PUT /status-pages/:id` update a status page
- `DELETE /status-pages/:id` delete a status page
- `POST /status-pages/:id/components` add a component
- `DELETE /status-pages/:id/components/:cid` remove a component
- `POST /status-pages/:id/components/bulk` bulk add components (max 50)
- `GET /status-pages/:id/groups` list component groups
- `POST /status-pages/:id/groups` create a component group
- `PUT /status-pages/:id/groups/:gid` update a component group
- `DELETE /status-pages/:id/groups/:gid` delete a component group

### Custom domains (paid plans only)
- `POST /status-pages/:id/custom-domain/analyze` analyze DNS for a custom domain
- `POST /status-pages/:id/custom-domain/apply` connect a custom domain (provisions SSL via Cloudflare)
- `POST /status-pages/:id/custom-domain/verify` verify CNAME is live and SSL is active
- `DELETE /status-pages/:id/custom-domain` remove a custom domain

Custom domains let paid users serve status pages at their own subdomain (e.g. `status.company.com`).
The user must CNAME their domain to `status-proxy.happyuptime.com`. Check `GET /project` → `limits.custom_domains` to see if the plan supports it.

### Alerts
- `GET /alerts/channels` list alert channels
- `POST /alerts/channels` create an alert channel
- `DELETE /alerts/channels/:id` delete an alert channel
- `GET /alerts/rules` list alert rules
- `POST /alerts/rules` create an alert rule
- `DELETE /alerts/rules/:id` delete an alert rule

### Analytics
- `GET /analytics/uptime` uptime history
- `GET /analytics/latency` latency percentiles
- `GET /analytics/sla` SLA compliance
- `GET /analytics/summary` dashboard summary

## Embeddable Widgets (Public, No Auth)

Widget URLs accept a **status page ID** to scope status to that page's components only. Use `GET /project` → `status_pages[].embeds` for ready-to-use URLs, or `embeds.badges` / `embeds.widgets` for the default page's URLs.

- Uptime badge: `GET /badges/{statusPageId}/uptime.svg?style=flat&period=30d`
- Status badge: `GET /badges/{statusPageId}/status.svg`
- Response time badge: `GET /badges/{statusPageId}/response-time.svg`
- Status JSON: `GET /widgets/{statusPageId}/status.json` (CORS-enabled)
- Downtime banner: `GET /widgets/{statusPageId}/embed.js`

Use `GET /project` → `status_pages[].public_url` or `embeds.links.status_page` for the canonical public URL. Do not guess routes from slugs.

## Heartbeat Monitoring (Public, No Auth)

For cron jobs and background tasks:
```bash
curl -X POST https://happyuptime.com/api/heartbeat/my-job-id
curl -X POST https://happyuptime.com/api/heartbeat/my-job-id -d '{"status":"ok","message":"Done"}'
```

## Claude Code Skill

Install the Happy Uptime skill for Claude Code:
```bash
mkdir -p .claude/skills/happyuptime && curl -fsSL https://happyuptime.com/skill.md -o .claude/skills/happyuptime/SKILL.md
```

Download: https://happyuptime.com/skill.md

## Notes for agents
- Prefer the OpenAPI document for exact request and response shapes.
- Treat all API routes as JSON endpoints.
- Use `Authorization: Bearer hu_...` exactly as written.
- Use `GET /project` → `status_pages[].public_url` or `embeds.links.status_page` as the canonical public status-page URL.
- Use the returned `embeds.snippets` values as-is for badges and widgets instead of constructing your own badge links.
- Published default routes are `/status/{slug}`, not `/s/{slug}`.
- If you see `401 Unauthorized`, first verify the header format and that the key was copied correctly.
- If a request returns 401, the API key is missing or invalid.
- If a request returns 403, the API key scope is insufficient.
- Claude Code skill: https://happyuptime.com/skill.md
