The pingy.io API

A small, predictable JSON API. Read the stored status of any site, run a live check on demand, or use an API key to manage and poll your own monitors.

🌐 Public — no key

Read the last-known up/down, status code, response time, and uptime for any host we’ve checked. Run live checks (free-tier budget). Rate-limited by IP.

🔑 With an API key — your account

List & poll your monitors with 30-day uptime and check history, and add monitors to your plan. Create a key in Settings (account required).

Base URL

https://pingy.io/api/v1

Authentication

Send your key as a Bearer token (or an X-Api-Key header). Public endpoints work without one; a key just unlocks per-account behaviour.

curl https://pingy.io/api/v1/monitors \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxxxxxx"

Keep keys secret — treat them like passwords. Revoke a leaked key anytime from Settings.

Rate limits

Limits are cost-based. Reads (stored data) are cheap; live checks of new sites are not. Reads return standard X-RateLimit-* headers; exceeding any limit returns 429 with Retry-After.

OperationLimit
Reads — stored status, your monitors15 / minute
Live check of a new / foreign site3 / hour
Live check of a site in your accountcounts as a read (15/min)

Reads are keyed by API key when present, otherwise by IP. The 3/hour live-check budget is per account (or per IP when anonymous). Want a site checked more often? Add it to your account — your monitors are checked on a schedule and polling them is just a read.

Endpoints

GET /api/v1/status/{host} public · read

The last-known status for a host. Returns known: false if we’ve never checked it (use POST /checks to check it live).

curl https://pingy.io/api/v1/status/example.com
{
  "host": "example.com",
  "known": true,
  "status": "up",
  "is_up": true,
  "last_status_code": 200,
  "response_ms": 184,
  "uptime_percent": 99.97,
  "total_checks": 4213,
  "last_checked_at": "2026-06-21T18:04:11+00:00",
  "page": "https://pingy.io/site/example.com"
}
POST /api/v1/checks public · live

Run a fresh check right now. Spends the 3/hour budget unless the host is already one of your monitors. Body: url (required), mode (http default, or ping).

curl -X POST https://pingy.io/api/v1/checks \
  -H "Content-Type: application/json" \
  -d '{"url":"example.com"}'
{
  "data": {
    "host": "example.com",
    "state": "up",
    "is_up": true,
    "status_code": 200,
    "response_ms": 173,
    "ip_address": "93.184.216.34",
    "checked_at": "2026-06-21T18:10:00+00:00",
    "monitored": false
  }
}
GET /api/v1/monitors key · read

Every monitor on your account with live status, plan, and 30-day uptime. Poll this freely (15/min).

{
  "data": [
    {
      "id": 42,
      "name": "Storefront",
      "url": "https://shop.example.com",
      "host": "shop.example.com",
      "plan": "enterprise",
      "status": "up",
      "is_up": true,
      "is_active": true,
      "uptime_30d": 99.98,
      "last_status_code": 200,
      "last_response_ms": 212,
      "interval_seconds": 60,
      "last_checked_at": "2026-06-21T18:03:00+00:00"
    }
  ]
}
POST /api/v1/monitors key · billed

Add a site to your account on a chosen plan. Body: url and plan (free, pro, or enterprise) are both required; optional name.

Billing: pro ($3/mo per site) and enterprise ($10/mo per site) are charged to your subscription immediately (prorated). A paid request needs a payment method already on file — otherwise it returns 402 and you set up billing on the web first. free respects your 3-site cap.
curl -X POST https://pingy.io/api/v1/monitors \
  -H "Authorization: Bearer pk_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{"url":"shop.example.com","plan":"pro"}'

Returns 201 with the created monitor, 409 if you already monitor that host.

GET /api/v1/monitors/{id} key · read

One monitor, plus its last 20 checks.

{
  "data": {
    "id": 42,
    "host": "shop.example.com",
    "plan": "enterprise",
    "status": "up",
    "uptime_30d": 99.98,
    "...": "…",
    "recent_checks": [
      {
        "state": "up",
        "is_up": true,
        "status_code": 200,
        "response_ms": 212,
        "ip_address": "203.0.113.10",
        "error": null,
        "checked_at": "2026-06-21T18:03:00+00:00"
      }
    ]
  }
}

Errors

Errors are JSON with an error code and a human message.

StatusMeaning
401Missing or invalid API key
402Paid monitor requested with no payment method on file
404Unknown host or monitor
409Host already monitored on your account
422Invalid URL, bad plan, or free-site cap reached
429Rate limit / hourly check budget exceeded — see Retry-After

Create a free account to get an API key.

Start free