API Reference
Base URL: https://api-sentinel.vercel.app — All endpoints return JSON. All write endpoints require authentication.
Authentication
All API requests must include your API key in the x-api-key header. API keys are scoped to your account — all monitors and usage logs are isolated per key.
// Include this header on every request
x-api-key: sk_live_xxxxxxxxxxxxxxxxxxxxError responses
Missing or invalid keys return a 401 with one of:
{ "error": "Missing x-api-key header" }
{ "error": "Invalid or inactive API key" }Validate an endpoint
Sends a one-off request to any URL and returns a structured health report. Checks are optional — omit any you don't need. Results are logged to your account's usage history.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The endpoint URL to validate |
| method | string | No | HTTP method. Defaults to "GET" |
| headers | object | No | Key-value pairs sent with the request |
| body | string | No | Raw request body (for POST/PUT requests) |
| checks.statusCode.expected | number | number[] | No | Expected HTTP status code(s) |
| checks.responseTiming.maxMs | number | No | Maximum acceptable response time in milliseconds |
| checks.ssl.enabled | boolean | No | Whether to validate the SSL certificate |
| checks.ssl.minDaysRemaining | number | No | Minimum days before cert expiry. Defaults to 14 |
Request example
{
"url": "https://api.example.com/health",
"method": "GET",
"headers": {
"Authorization": "Bearer token123"
},
"checks": {
"statusCode": {
"expected": 200
},
"responseTiming": {
"maxMs": 1000
},
"ssl": {
"enabled": true,
"minDaysRemaining": 30
}
}
}Response — 200 OK
{
"url": "https://api.example.com/health",
"timestamp": "2026-05-09T12:00:00.000Z",
"passed": true,
"durationMs": 243,
"statusCode": 200,
"checks": [
{
"name": "status_code",
"passed": true,
"message": "Status code 200 is as expected",
"details": {
"statusCode": 200,
"expected": [200]
}
},
{
"name": "response_timing",
"passed": true,
"message": "Response time 243ms is within the 1000ms limit",
"details": {
"durationMs": 243,
"maxMs": 1000
}
},
{
"name": "ssl",
"passed": true,
"message": "SSL certificate valid, 187 days until expiry",
"details": {
"valid": true,
"expiryDate": "2026-11-12T00:00:00.000Z",
"daysRemaining": 187,
"issuer": { "O": "Let's Encrypt" },
"subject": { "CN": "api.example.com" }
}
}
]
}Response — check failure
When one or more checks fail, passed is false and the failing check carries a descriptive message. The HTTP status is still 200 — the status code reflects the API call, not the target.
{
"url": "https://api.example.com/health",
"timestamp": "2026-05-09T12:00:00.000Z",
"passed": false,
"durationMs": 1847,
"statusCode": 200,
"checks": [
{
"name": "status_code",
"passed": true,
"message": "Status code 200 is as expected",
"details": { "statusCode": 200, "expected": [200] }
},
{
"name": "response_timing",
"passed": false,
"message": "Response time 1847ms exceeded the 1000ms limit",
"details": { "durationMs": 1847, "maxMs": 1000 }
}
]
}Create a monitor
Registers an endpoint for continuous monitoring. The cron runner checks all active monitors on schedule and sends an email alert to alert_email whenever a monitor fails.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Human-readable label for this monitor |
| url | string | Yes | The endpoint URL to monitor |
| method | string | No | HTTP method. Defaults to "GET" |
| headers | object | No | Key-value pairs sent with each check request |
| interval | string | No | Check frequency: "1m", "5m", "1h". Defaults to "5m" |
| checks | object | No | Same check options as POST /api/v1/validate |
| alert_email | string | No | Email for failure alerts. Defaults to your account email |
Request example
{
"name": "Production API",
"url": "https://api.example.com/health",
"method": "GET",
"interval": "5m",
"checks": {
"statusCode": {
"expected": 200
},
"responseTiming": {
"maxMs": 2000
},
"ssl": {
"enabled": true,
"minDaysRemaining": 14
}
},
"alert_email": "you@example.com"
}Response — 201 Created
{
"monitor_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "active"
}List monitors
Returns all monitors associated with your API key, ordered by creation date descending.
Response — 200 OK
{
"monitors": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Production API",
"url": "https://api.example.com/health",
"method": "GET",
"interval": "5m",
"is_active": true,
"alert_email": "you@example.com",
"checks": {
"statusCode": { "expected": 200 },
"responseTiming": { "maxMs": 2000 }
},
"created_at": "2026-05-09T12:00:00.000Z"
}
]
}Get a monitor
Returns a single monitor along with its 20 most recent check results. Use this to inspect historical pass/fail status and response times.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | Yes | The monitor ID returned when it was created |
Response — 200 OK
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Production API",
"url": "https://api.example.com/health",
"method": "GET",
"interval": "5m",
"is_active": true,
"alert_email": "you@example.com",
"created_at": "2026-05-09T12:00:00.000Z",
"recent_checks": [
{
"id": "abc12300-0000-0000-0000-000000000001",
"status_code": 200,
"response_time": 243,
"passed": true,
"created_at": "2026-05-09T12:05:00.000Z"
},
{
"id": "abc12300-0000-0000-0000-000000000002",
"status_code": 503,
"response_time": 4821,
"passed": false,
"created_at": "2026-05-09T12:00:00.000Z"
}
]
}Response — 404 Not Found
{ "error": "Monitor not found" }Deactivate a monitor
Deactivates a monitor — it will no longer run scheduled checks or send alerts. The monitor record and its check history are preserved. This action can be reversed by contacting support or re-creating the monitor.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | Yes | The monitor ID to deactivate |
Response — 200 OK
{ "status": "deactivated" }