API Overview
The WatchCron REST API lets you manage cron job checks, view ping history, and query notification channels programmatically. Every action you can take in the dashboard is available through the API.
Base URL
All API endpoints use the following base URL:
https://watchcron.com/api/v1
Authentication
Every request must include your API key in the Authorization header as a Bearer token. You can generate API keys in your dashboard under Project Settings → API Keys.
Each API key is scoped to a single project. Checks, pings, and channels returned by the API belong to that project only.
curl -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ https://watchcron.com/api/v1/checks
Required headers
| Header | Value | Required |
|---|---|---|
Authorization | Bearer YOUR_API_KEY | Always |
Content-Type | application/json | POST / PUT requests |
Accept | application/json | Recommended |
Rate limits
API requests are rate-limited per API key on a 60-second rolling window. The limit depends on your plan:
| Plan | Requests / minute |
|---|---|
| Free | 100 |
| Starter | 200 |
| Pro | 500 |
| Business | 1,000 |
When you exceed the limit, the API returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait before retrying.
HTTP/1.1 429 Too Many Requests Retry-After: 45 { "error": "Rate limit exceeded", "retry_after": 45 }
Pagination
Endpoints that return lists use offset-based pagination. Pass per_page (default: 25) and page as query parameters. Every paginated response includes a meta.pagination object:
{
"data": [...],
"meta": {
"pagination": {
"total": 87,
"per_page": 25,
"current_page": 1,
"last_page": 4
}
}
}
Error responses
The API uses standard HTTP status codes. Error responses include a JSON body with an error field:
| Status | Meaning | When |
|---|---|---|
200 | OK | Request succeeded |
201 | Created | Resource created successfully |
204 | No Content | Resource deleted successfully |
401 | Unauthorized | Missing or invalid API key |
404 | Not Found | Resource does not exist or belongs to another project |
422 | Validation Error | Invalid request body (e.g. bad cron expression) |
429 | Rate Limited | Too many requests — wait and retry |
500 | Server Error | Unexpected error on our side |
HTTP/1.1 401 Unauthorized { "error": "Invalid API key" }
Quick start
Here's a minimal example that creates a check and sends its first ping — the two steps needed to start monitoring a cron job:
curl -X POST https://watchcron.com/api/v1/checks \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "DB Backup", "schedule_type": "cron", "cron_expression": "0 3 * * *", "grace_seconds": 300 }'
The response contains the ping_url — add it to the end of your cron job:
# crontab -e 0 3 * * * /usr/local/bin/backup.sh && curl -fsS --retry 3 https://watchcron.com/ping/YOUR-CHECK-UUID
Endpoints overview
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/checks | List all checks |
| POST | /api/v1/checks | Create a check |
| GET | /api/v1/checks/{uuid} | Get check details |
| PUT | /api/v1/checks/{uuid} | Update a check |
| DELETE | /api/v1/checks/{uuid} | Delete a check |
| PATCH | /api/v1/checks/{uuid}/pause | Pause or unpause |
| GET | /api/v1/checks/{uuid}/pings | List ping history |
| GET | /api/v1/checks/{uuid}/flips | List status changes |
| GET | /api/v1/channels | List notification channels |
Ping endpoints (no auth required)
Ping endpoints are separate from the REST API. They accept both GET and POST requests and do not require authentication — just the check UUID or slug in the URL:
| Method | Endpoint | Description |
|---|---|---|
| ANY | /ping/{uuid} | Report success |
| ANY | /ping/{uuid}/start | Signal job started |
| ANY | /ping/{uuid}/fail | Report failure |
| POST | /ping/{uuid}/log | Attach log output (max 100 KB) |
Versioning
The current API version is v1. The version is included in the URL path. We will not introduce breaking changes within a version. If a new version is released, v1 will continue to work for at least 12 months after the announcement.