Enori API Documentation
The Enori API lets you manage monitors, incidents, alerts, status pages, and more programmatically. All endpoints use REST conventions with JSON request and response bodies.
Base URL: https://api.enori.io
Quick Start
Get monitoring set up in three steps.
1. Get Your API Key
Navigate to Settings → API Keys in your dashboard and create a new key. Choose scopes based on what you need:
| Scope | Access |
|---|---|
monitors:read | List and view monitors |
monitors:write | Create, update, delete, pause/resume monitors |
incidents:read | List and view incidents |
status-pages:read | List and view status pages |
status-pages:write | Create, update, delete status pages |
teams:read | List teams and members |
teams:write | Manage teams |
* | Full access (all scopes) |
2. Make Your First Request
curl -H "X-API-Key: YOUR_API_KEY" https://api.enori.io/api/monitors3. Set Up Alerts
Create a webhook alert channel to receive real-time notifications when monitors go down or recover:
curl -X POST https://api.enori.io/api/alert-channels \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "My Webhook",
"type": "Webhook",
"webhookUrl": "https://your-server.com/webhook"
}'Authentication
All API requests require an API key passed in the X-API-Key header:
curl -H "X-API-Key: YOUR_API_KEY" https://api.enori.io/api/monitorsAPI keys are scoped — choose the minimum permissions needed. Keys can be created and managed at Settings → API Keys or via the /api/keys endpoint.
Never share your API key. Treat it like a password. If compromised, revoke it immediately from the dashboard and create a new one.
Managing API Keys
Create a new API key. The full key is returned only once in the response — store it securely.
{
"name": "CI/CD Pipeline",
"scopes": ["monitors:read", "monitors:write"]
}List all API keys (key values are masked).
Revoke and delete an API key.
Rate Limits
Rate limits protect the API from abuse. Limits are applied per API key.
| Endpoint | Limit |
|---|---|
| General API calls | 100 / minute |
| Read operations | 200 / minute |
| Create monitor | 10 / hour |
| Check now | 5 / minute |
| Test alert | 5 / minute |
When rate limited, the API returns HTTP 429 Too Many Requests with these headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed |
X-RateLimit-Remaining | Requests remaining in window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Retry-After | Seconds to wait before retrying |
Monitors
List Monitors
Query parameters:
| Parameter | Type | Description |
|---|---|---|
tag | string | Filter by tag (repeat for AND logic: ?tag=prod&tag=api) |
type | string | Filter by type: Website, Ping, Port, Dns, Domain, Job |
curl -H "X-API-Key: YOUR_API_KEY" \
"https://api.enori.io/api/monitors?type=Website"Response:
{
"items": [
{
"id": "mon_abc123",
"name": "Production API",
"type": "Website",
"url": "https://api.example.com",
"status": "Up",
"uptimePercentage": 99.95,
"lastCheckedAt": "2026-03-24T10:30:00Z",
"intervalSeconds": 60
}
],
"totalCount": 1
}Get Monitor
Returns full monitor details including configuration and current state.
Create Monitor
{
"name": "Production API",
"type": "Website",
"url": "https://api.example.com",
"intervalSeconds": 60,
"timeoutSeconds": 30,
"httpMethod": "GET",
"expectedStatusCode": 200,
"failureThreshold": 2,
"alertOnDown": true,
"alertOnRecovered": true,
"alertChannelIds": ["ch_abc123"],
"regions": ["UsEast", "EuWest"],
"tags": ["production", "api"]
}Monitor types:
| Type | Value | Use For |
|---|---|---|
Website | 10 | HTTP/HTTPS endpoints, APIs, websites |
Ping | 3 | ICMP ping checks |
Port | 2 | TCP port availability |
Dns | 4 | DNS record monitoring |
Domain | 6 | Domain expiry tracking |
Job | 8 | Cron job / heartbeat monitoring |
Update Monitor
Send the full monitor configuration. Fields not included will be reset to defaults.
Upsert by Name
Idempotent — creates if not exists, updates if exists. Always returns 200. Ideal for infrastructure-as-code and Terraform workflows. The URL name takes precedence over the body name.
Delete Monitor
Permanently deletes the monitor and all associated data (check results, incidents, alerts).
Pause and Resume
Pausing stops checks and alerts. Resuming triggers an immediate check.
Trigger Immediate Check
Triggers an on-demand check outside the regular interval. Rate limited to 5 per minute.
Check Results
Returns recent check results with response time, status code, and error details.
Statistics
Incidents
List Incidents
Returns { items: [...], totalCount: N }.
| Parameter | Type | Description |
|---|---|---|
monitorId | string | Filter by monitor |
status | string | Filter by status |
from | datetime | Start date (ISO 8601) |
to | datetime | End date (ISO 8601) |
limit | int | Max results (default 50) |
offset | int | Pagination offset |
Recent and Active Incidents
Get Incident
Create Manual Incident
Acknowledge
Stops escalation timers for this incident.
Resolve
Add Update
Post a status update to the incident timeline.
Incident Statistics
Incidents by Monitor
Alerts
List Alert Records
| Parameter | Type | Description |
|---|---|---|
monitorId | string | Filter by monitor |
status | string | Filter by delivery status |
type | string | Alert type (Down, Recovered, P95, etc.) |
from | datetime | Start date |
to | datetime | End date |
limit | int | Max results |
offset | int | Pagination offset |
Alert Channels
Manage where alerts are delivered.
Supported channel types: Email, Slack, Discord, Teams, Webhook
Alert Rules
Configure which monitors trigger which channels.
Job Monitoring
Enori's Job monitor type tracks cron jobs and scheduled tasks using heartbeat pings.
How It Works
- Create a Job monitor with a cron expression defining your expected schedule
- Get the unique ping token from the monitor details
- Add ping calls to your job script — Enori alerts you if pings stop arriving
Ping Endpoints
These endpoints require no authentication — just the unique token.
Report job success (heartbeat).
Report job failure.
Report job start (enables runtime tracking).
All three endpoints accept GET, HEAD, and POST methods.
Example: Shell Cron Job
#!/bin/bash
# Notify Enori the job has started
curl -fsS -m 10 https://api.enori.io/ping/YOUR_TOKEN/start
# Run the actual job
/usr/bin/backup-database.sh
# Report success or failure based on exit code
if [ $? -eq 0 ]; then
curl -fsS -m 10 https://api.enori.io/ping/YOUR_TOKEN
else
curl -fsS -m 10 https://api.enori.io/ping/YOUR_TOKEN/fail
fiExample: GitHub Actions
name: Nightly Build
on:
schedule:
- cron: '0 2 * * *'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: curl -fsS https://api.enori.io/ping/${{ secrets.ENORI_TOKEN }}/start
- run: npm ci && npm run build
- run: curl -fsS https://api.enori.io/ping/${{ secrets.ENORI_TOKEN }}
if: success()
- run: curl -fsS https://api.enori.io/ping/${{ secrets.ENORI_TOKEN }}/fail
if: failure()Example: Python Script
import requests
import sys
TOKEN = "YOUR_TOKEN"
BASE = "https://api.enori.io/ping"
# Signal start
requests.get(f"{BASE}/{TOKEN}/start", timeout=10)
try:
# Your job logic here
run_etl_pipeline()
requests.get(f"{BASE}/{TOKEN}", timeout=10)
except Exception:
requests.get(f"{BASE}/{TOKEN}/fail", timeout=10)
sys.exit(1)Ping History
Returns the heartbeat history for a Job monitor including execution times, status, and messages.
Status Pages
Authenticated Endpoints
Public Endpoints (No Auth)
View a public status page — returns component statuses, uptime data, and incident history.
Subscribe to status page updates via email.
Webhooks
When you create a Webhook alert channel, Enori will POST JSON payloads to your URL whenever monitor events occur.
Payload Format
{
"event": "monitor.down",
"monitor": {
"id": "mon_abc123",
"name": "Production API",
"url": "https://api.example.com",
"type": "Website"
},
"alert": {
"type": "Down",
"message": "HTTP 503 Service Unavailable",
"timestamp": "2026-03-24T14:30:00Z",
"responseTimeMs": 5230
}
}Event Types
| Event | Description |
|---|---|
monitor.down | Monitor detected as down |
monitor.up | Monitor recovered |
monitor.degraded | Performance degradation (P95 threshold exceeded) |
monitor.ssl_expiring | SSL certificate expiring soon |
incident.created | New incident created |
incident.resolved | Incident resolved |
Security
Verify webhook authenticity by checking:
- The
User-Agentheader containsEnori-Webhook/1.0 - The request arrives within seconds of the event timestamp
- Your endpoint URL uses HTTPS
Retry Policy
Failed webhook deliveries (non-2xx response or timeout) are retried:
- Up to 3 retries with exponential backoff: 30s, 5m, 30m
- After all retries fail, the delivery is marked as failed
- Failed deliveries are visible in your alert history
Uptime Badges
Embed uptime and status badges in your README, documentation, or status page.
Uptime Badge
Status Badge
Parameters
| Parameter | Default | Options | Description |
|---|---|---|---|
period | 30d | 24h, 7d, 30d, 90d | Time range (uptime badge only) |
label | uptime / status | Any string (max 30 chars) | Left side label text |
style | flat | flat, flat-square | Badge style |
Embed in Markdown

Embed in HTML
<img src="https://api.enori.io/api/badges/mon_abc123/uptime.svg" alt="Uptime" />Badges are cached for 5 minutes. Returns a gray "unknown" badge if the monitor is not found or inactive.
Error Responses
The API uses standard HTTP status codes and returns JSON error bodies.
Status Codes
| Code | Description |
|---|---|
200 | Success |
201 | Created |
202 | Accepted (async operation started) |
204 | No Content (successful deletion) |
400 | Bad Request — validation error |
401 | Unauthorized — missing or invalid API key |
403 | Forbidden — insufficient scope or plan limit exceeded |
404 | Not Found |
429 | Too Many Requests — rate limit exceeded |
500 | Internal Server Error |
Error Format
{
"error": "Monitor limit exceeded",
"message": "Your Base plan allows 10 monitors. Upgrade to Pro for up to 50.",
"code": "PLAN_LIMIT_EXCEEDED"
}Common Errors
| Scenario | Code | What to Do |
|---|---|---|
| Invalid API key | 401 | Check the key is correct and not revoked |
| Missing required scope | 403 | Create a new key with the required scope |
| Plan limit exceeded | 403 | Upgrade your plan or remove unused resources |
| Rate limited | 429 | Wait for Retry-After seconds, then retry |
| Invalid request body | 400 | Check the error message for field-level details |
Plan Limits
| Limit | Base (€5.99/mo) | Pro (€11.99/mo) | Business (€29.99/mo) |
|---|---|---|---|
| Monitors | 10 | 50 | 200 |
| Check Interval | 60s | 60s | 60s |
| Data Retention | 30 days | 60 days | 90 days |
| API Keys | 2 | 10 | 50 |
| Alert Channels | 5 | 15 | Unlimited |
| Teams | 2 | 10 | Unlimited |
| Members per Team | 3 | 10 | 25 |
| Status Pages | 3 | 10 | 50 |
| Escalation Policies | 2 | 10 | 20 |
| Maintenance Windows | 2 | 10 | Unlimited |
| Reports per Month | 3 | 10 | Unlimited |
Add-ons (available on any plan):
| Add-on | Price | Effect |
|---|---|---|
| Extra Monitor | €0.50/month each | +1 to your plan's monitor limit |
| 30s Check Interval | €3.00/month | Unlock 30-second checks (account-wide) |
All plans include a 14-day free trial.
Code Examples
cURL
# List all monitors
curl -H "X-API-Key: YOUR_API_KEY" \
https://api.enori.io/api/monitors
# Create a website monitor
curl -X POST https://api.enori.io/api/monitors \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Production API",
"type": "Website",
"url": "https://api.example.com/health",
"intervalSeconds": 60,
"expectedStatusCode": 200,
"alertOnDown": true,
"alertOnRecovered": true
}'
# Pause a monitor
curl -X POST -H "X-API-Key: YOUR_API_KEY" \
https://api.enori.io/api/monitors/mon_abc123/pause
# Trigger an immediate check
curl -X POST -H "X-API-Key: YOUR_API_KEY" \
https://api.enori.io/api/monitors/mon_abc123/checkPython
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://api.enori.io"
HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
# Create a monitor
monitor = requests.post(f"{BASE}/api/monitors", headers=HEADERS, json={
"name": "Staging API",
"type": "Website",
"url": "https://staging.example.com",
"intervalSeconds": 300,
"expectedStatusCode": 200,
}).json()
print(f"Created monitor: {monitor['id']}")
# List all monitors
data = requests.get(f"{BASE}/api/monitors", headers=HEADERS).json()
for m in data["items"]:
print(f" {m['name']}: {m['status']} ({m['uptimePercentage']:.2f}%)")
# Get recent incidents
incidents = requests.get(
f"{BASE}/api/incidents/recent", headers=HEADERS
).json()
for inc in incidents:
print(f" [{inc['status']}] {inc['title']}")Node.js
const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.enori.io";
async function enori(path, options = {}) {
const res = await fetch(\`\${BASE}\${path}\`, {
...options,
headers: {
"X-API-Key": API_KEY,
"Content-Type": "application/json",
...options.headers,
},
});
if (!res.ok) throw new Error(\`\${res.status}: \${await res.text()}\`);
return res.json();
}
// Create a monitor
const monitor = await enori("/api/monitors", {
method: "POST",
body: JSON.stringify({
name: "Checkout Service",
type: "Website",
url: "https://checkout.example.com/health",
intervalSeconds: 60,
}),
});
console.log(\`Created: \${monitor.id}\`);
// List all monitors
const { items } = await enori("/api/monitors");
items.forEach((m) => console.log(\`\${m.name}: \${m.status}\`));GitHub Actions
name: Deploy and Verify Uptime
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build && npm run deploy
- name: Verify monitors after deploy
env:
ENORI_KEY: ${{ secrets.ENORI_API_KEY }}
run: |
sleep 30
RESPONSE=$(curl -s -H "X-API-Key: $ENORI_KEY" \
"https://api.enori.io/api/monitors?tag=production")
echo "$RESPONSE" | jq '.items[] | "\(.name): \(.status)"'
DOWN=$(echo "$RESPONSE" | jq '[.items[] | select(.status == "Down")] | length')
if [ "$DOWN" -gt 0 ]; then
echo "::error::$DOWN production monitors are down!"
exit 1
fiInteractive API Explorer
For a complete interactive reference with all endpoints, request/response schemas, and the ability to try requests directly, visit the Scalar API documentation:
The OpenAPI 3.0 specification is also available programmatically:
curl https://api.enori.io/openapi/v1.json