A team I know found out their API was down because a customer tweeted about it. 45 minutes of downtime before they even knew. With Better Stack, they'd have known in 30 seconds.
What Better Stack Offers for Free
Better Stack (formerly Better Uptime) free tier:
- 10 monitors with 3-minute check interval
- Uptime monitoring — HTTP, ping, TCP, DNS, SSL
- Status pages — branded public status page
- Incident management — on-call schedules, escalations
- Logs — 1 GB/month with 3-day retention
- Heartbeats — cron job monitoring
- Email and push notifications
Quick Start
# Create a monitor via API
curl -X POST 'https://uptime.betterstack.com/api/v2/monitors' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"monitor_type": "status",
"url": "https://yourapp.com/api/health",
"pronounceable_name": "Production API",
"check_frequency": 180,
"request_timeout": 15,
"confirmation_period": 0
}'
Monitor Management
const BETTER_STACK_TOKEN = process.env.BETTER_STACK_TOKEN;
const BASE_URL = 'https://uptime.betterstack.com/api/v2';
async function apiCall(method, endpoint, body) {
const res = await fetch(`${BASE_URL}${endpoint}`, {
method,
headers: {
'Authorization': `Bearer ${BETTER_STACK_TOKEN}`,
'Content-Type': 'application/json'
},
body: body ? JSON.stringify(body) : undefined
});
return res.json();
}
// List all monitors
const { data: monitors } = await apiCall('GET', '/monitors');
monitors.forEach(m => {
console.log(`${m.attributes.pronounceable_name}: ${m.attributes.status}`);
});
// Create monitor
await apiCall('POST', '/monitors', {
monitor_type: 'status',
url: 'https://api.example.com/health',
pronounceable_name: 'API Health Check',
check_frequency: 60
});
// Pause a monitor
await apiCall('POST', `/monitors/${monitorId}/pause`);
Heartbeat Monitoring (Cron Jobs)
# Create a heartbeat monitor
curl -X POST 'https://uptime.betterstack.com/api/v2/heartbeats' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Daily Backup Job",
"period": 86400,
"grace": 3600
}'
# Ping it from your cron job
# Add to end of your script:
curl https://uptime.betterstack.com/api/v1/heartbeat/YOUR_HEARTBEAT_ID
Incident Management
# List incidents
curl 'https://uptime.betterstack.com/api/v2/incidents' \
-H 'Authorization: Bearer YOUR_API_TOKEN'
# Acknowledge an incident
curl -X POST 'https://uptime.betterstack.com/api/v2/incidents/INCIDENT_ID/acknowledge' \
-H 'Authorization: Bearer YOUR_API_TOKEN'
# Resolve an incident
curl -X POST 'https://uptime.betterstack.com/api/v2/incidents/INCIDENT_ID/resolve' \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Status Page
# Create a status page
curl -X POST 'https://uptime.betterstack.com/api/v2/status-pages' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"company_name": "Your App",
"company_url": "https://yourapp.com",
"subdomain": "status",
"timezone": "UTC"
}'
# Add resources to status page
curl -X POST 'https://uptime.betterstack.com/api/v2/status-pages/SP_ID/resources' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"resource_id": "MONITOR_ID",
"resource_type": "Monitor",
"public_name": "API"
}'
Log Management
# Ingest logs
curl -X POST 'https://in.logs.betterstack.com/' \
-H 'Authorization: Bearer YOUR_SOURCE_TOKEN' \
-H 'Content-Type: application/json' \
-d '[
{"dt": "2026-03-29T10:00:00Z", "level": "error", "message": "Payment failed", "order_id": "123"},
{"dt": "2026-03-29T10:01:00Z", "level": "info", "message": "User signed up", "user_id": "456"}
]'
Need to monitor websites for changes? Check out my web scraping actors on Apify — automated web monitoring.
Need custom monitoring? Email me at spinov001@gmail.com.
Top comments (0)