Pingolab
API v1
DEVELOPER API v1

Pingolab REST API

Everything you can do in the panel, you can do with the API โ€” manage monitors, read uptime and response times, handle incidents and status pages. It also powers our future mobile app, so it is here to stay.

Base URL https://panel.pingolab.net/api/v1
Explore Endpoints
Bearer Token Auth JSON UTF-8 & ULID Idempotent POST HMAC-SHA256 Webhooks

Authentication

Create a key in the panel (Settings โ†’ API keys) and send it as a Bearer token. Keys are shown once and stored hashed. There are three kinds:

Full Read / Write

Full access โ€” read and write.

Read-Only GET Only

Read-only โ€” every GET endpoint.

Monitor Widget Safe

Monitor-specific โ€” reads one monitor only; safe for public widgets.

HTTP Header
Authorization: Bearer pl_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Response format

JSON with snake_case keys. Timestamps are ISO 8601 in UTC; ids are public ULIDs. Single resources and lists are wrapped in data, with meta and links for pagination.

Envelope JSON
{
    "data": {
        "id": "01J8Z3ABCD1234EXAMPLE01",
        "type": "http",
        "name": "Production Website",
        "url": "https://example.com",
        "status": "up",
        "interval_seconds": 60,
        "created_at": "2026-09-28T10:00:00+00:00"
    },
    "meta": {
        "next_cursor": "eyJpZCI6IjAxSjha..."
    },
    "links": {
        "next": "https://panel.pingolab.net/api/v1/monitors?cursor=eyJpZCI6IjAxSjha..."
    }
}

Errors

Errors always have the same shape. The code is stable and documented; the message follows your Accept-Language header (tr or en).

Error Payload
{
    "error": {
        "code": "validation_failed",
        "message": "The given data was invalid.",
        "details": {
            "url": [
                "The url field must be a valid URL."
            ]
        }
    }
}
Error Code HTTP
unauthenticated 401
forbidden 403
not_found 404
method_not_allowed 405
idempotency_in_progress 409
validation_failed 422
idempotency_mismatch 422
rate_limited 429
server_error 500

Pagination

Lists use cursor pagination: pass ?limit= (max 100, default 25) and follow links.next or meta.next_cursor via ?cursor=.

?limit=25&cursor=โ€ฆ

Rate limits

60 requests per minute per key by default. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; over the limit you get 429 with Retry-After.

X-RateLimit-Limit: 60

Idempotency

Send an Idempotency-Key header with POST requests to retry safely: the first response is stored for 24 hours and replayed (Idempotent-Replayed: true). Reusing a key with a different body returns idempotency_mismatch.

Idempotency-Key: <uuid>

Code examples

Make HTTP requests in your preferred programming language. All requests require a valid Bearer token.

# 1. List Monitors (GET)
curl https://panel.pingolab.net/api/v1/monitors \
  -H "Authorization: Bearer pl_your_key" \
  -H "Accept: application/json"

# 2. Create HTTP Monitor (POST)
curl -X POST https://panel.pingolab.net/api/v1/monitors \
  -H "Authorization: Bearer pl_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 5f1c98a2-d4b3-4f9e-8c67-1234567890ab" \
  -d '{
    "type": "http",
    "name": "Production Website",
    "url": "https://example.com",
    "interval_seconds": 60
  }'

Webhooks

Webhook alert channels receive a JSON POST for every event. Each request is signed with HMAC-SHA256 over "timestamp.body" using the channel's signing secret. We retry up to 3 times with backoff.

Events:
down up ssl_expiring ssl_expired heartbeat_missed reminder flapping_summary test
Sample Webhook Delivery
X-Pingolab-Event: down
X-Pingolab-Timestamp: 1790335924
X-Pingolab-Signature: sha256=a1b2c3d4e5f67890123456789abcdef0123456789abcdef0123456789abcdef0

{
    "event": "down",
    "occurred_at": "2026-09-28T12:00:00+00:00",
    "monitor": {
        "id": "01J8Z3ABCD1234EXAMPLE01",
        "name": "Production Website",
        "type": "http",
        "url": "https://example.com",
        "status": "down"
    },
    "incident": {
        "id": "01J8Z4XYZ9876INCIDENT01",
        "started_at": "2026-09-28T11:59:00+00:00",
        "resolved_at": null,
        "duration_seconds": null,
        "error_type": "timeout",
        "error_message": "Connection timed out after 10000ms"
    },
    "details": {},
    "links": {
        "monitor": "https://panel.pingolab.net/monitors/01J8Z3ABCD1234EXAMPLE01"
    }
}

Verifying the signature (constant-time)

Verify HMAC-SHA256 signatures to ensure webhook payloads originate from Pingolab and have not been tampered with. Always use constant-time string comparison to prevent timing attacks.

// PHP (HMAC-SHA256 Timing-Safe Verification)
$payload = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_PINGOLAB_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_PINGOLAB_SIGNATURE'] ?? '';

$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $payload, $secret);

// Replay protection (5 minutes tolerance)
if (abs(time() - (int) $timestamp) > 300 || ! hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid webhook signature');
}

// Process event safely
$event = json_decode($payload, true);

Endpoint reference

Explore all endpoints, test schemas, and send live requests directly from your browser.