Documentation

Tymo monitors cron jobs and scheduled tasks by waiting for an HTTP ping. Your job runs normally — at the end, it calls a URL. If that call never arrives, you get an alert. No agents. No SDKs. One line.

Quick start#

Three steps. The whole thing takes about 60 seconds.

1

Create a monitor

Sign in, create an organisation, then create a monitor. Give it a name, pick a schedule (every 24h or a cron expression), and set a grace period. Tymo generates a unique ping token.

2

Copy your ping URL

Your ping URL looks like this:

https://api.tymo.site/p/YOUR_TOKEN
3

Add one line to your job

Append a curl at the end of your cron job. Your job runs exactly as before — the ping fires on success.

# Your existing crontab entry
0 2 * * * /scripts/backup.sh

# With Tymo — only pings on success
0 2 * * * /scripts/backup.sh && curl -fsS https://api.tymo.site/p/YOUR_TOKEN

Done. Tymo now expects a ping every 24 hours. Miss the window by more than your grace period and your team gets an email.

The ping URL#

Every monitor gets a single ping endpoint. Call it when your job finishes successfully. The token is 16 characters and is unique to the monitor.

Endpoint
GET  https://api.tymo.site/p/:token
POST https://api.tymo.site/p/:token

Both GET and POST are accepted — use whichever your tooling supports. No authentication headers are needed.

Response

On success:

HTTP/1.1 200 OK

{ "ok": true }

Paused checks

If the monitor is paused, pings are accepted (200 { ok: true }) but have no effect — state is not updated, the next expected window is not recalculated, and no alerts are triggered. The ping is still logged.

Rate limit: A single ping token accepts a maximum of 10 requests per 60-second window. Exceeding this returns 429. Normal cron jobs will never hit this — it exists to prevent runaway loops.

Integration examples#

Replace YOUR_TOKEN with the token from your monitor's ping URL. Use -fsSwith curl: -f exits non-zero on HTTP errors, -s suppresses progress output,-S still shows errors.

Bash / cron

crontab
# Ping only fires when the job exits 0
0 2 * * * /scripts/backup.sh && curl -fsS https://api.tymo.site/p/YOUR_TOKEN

# Suppress curl output from cron email
0 2 * * * /scripts/backup.sh && curl -fsS https://api.tymo.site/p/YOUR_TOKEN > /dev/null 2>&1 || true

Python

python
import urllib.request
import sys

PING_URL = "https://api.tymo.site/p/YOUR_TOKEN"

def main():
    # your job code here
    do_backup()

try:
    main()
    urllib.request.urlopen(PING_URL)  # fires on success
except Exception as e:
    print(f"Job failed: {e}", file=sys.stderr)
    sys.exit(1)

Node.js

node.js
const https = require('node:https')

const PING_URL = 'https://api.tymo.site/p/YOUR_TOKEN'

async function main() {
  await doBackup()  // throws on failure

  // Ping on success
  await new Promise((resolve, reject) => {
    https.get(PING_URL, res => {
      res.resume()
      res.on('end', resolve)
    }).on('error', reject)
  })
}

main().catch(err => { console.error(err); process.exit(1) })

GitHub Actions

yaml
steps:
  - name: Run backup
    run: /scripts/backup.sh

  - name: Ping Tymo
    if: success()  # only on success
    run: curl -fsS https://api.tymo.site/p/YOUR_TOKEN
Use if: success() to ensure the ping only fires when all prior steps passed. GitHub Actions sets this automatically when using && chaining, but the explicit conditional is clearer.

Kubernetes CronJob

yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: db-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: Never
          containers:
          - name: backup
            image: your-image:latest
            command:
            - /bin/sh
            - -c
            - |
              /scripts/backup.sh
              curl -fsS https://api.tymo.site/p/YOUR_TOKEN
The shell | block runs commands sequentially. If backup.sh exits non-zero, the container exits before the curl runs, and Kubernetes marks the Job as failed — no ping is sent, which is exactly what you want.

Schedules#

When creating a monitor you choose a scheduleType and provide ascheduleValue. Tymo uses these to calculate when the next ping is expected.

Interval

A repeating fixed duration. The format is a number followed by a unit:m (minutes), h (hours), or d (days).

# Every 30 minutes
scheduleValue: "30m"

# Every 6 hours
scheduleValue: "6h"

# Every 24 hours (daily)
scheduleValue: "24h"

# Every 7 days (weekly)
scheduleValue: "7d"

Cron expression

Standard 5-field cron syntax: minute hour day-of-month month day-of-week. Useful when the job runs at a specific time of day rather than on a rolling interval.

# 2:00 AM every day
scheduleValue: "0 2 * * *"

# Every Monday at 09:00
scheduleValue: "0 9 * * 1"

# First day of each month at midnight
scheduleValue: "0 0 1 * *"
Cron expressions are validated server-side. If an expression is invalid, the monitor will not be created.

Grace periods#

A grace period is how long Tymo waits after the expected ping window before declaring a check down and sending an alert. The default is 30 minutes.

Example: your backup job is scheduled for 02:00 and usually finishes by 02:20. Set a grace period of 30 minutes. If no ping arrives by 02:30, an alert fires. A ping at 02:25 is still accepted as on-time.

SettingValue
Minimum1 minute
Maximum1440 minutes (24 hours)
Default30 minutes
Set your grace period to be longer than your longest expected job runtime. If a job normally takes 20 minutes but occasionally takes 45 minutes due to load, set your grace period to at least 60 minutes.

IP allowlisting#

By default, any IP address can ping your monitor URL. On the Pro plan, you can restrict accepted pings to a list of known source IPs or CIDR ranges.

If the allowedIps list is non-empty and a ping arrives from an IP not on the list, it is rejected with 403 IP not allowed before any state is updated. The rejection is logged.

Supported formats

# Single IPv4 address
"192.168.1.100"

# CIDR range — matches the whole /24 subnet
"10.0.1.0/24"

# Multiple entries — any match allows the ping
"10.0.0.0/8"
"203.0.113.42"
Empty list = no restriction. If allowedIps is empty (the default), Tymo accepts pings from any source. Add entries only when you know the fixed IP(s) your job runs from.
Cloud runners have dynamic IPs. GitHub Actions, Lambda, and similar services assign new IPs each run. IP allowlisting is most reliable for jobs running on fixed infrastructure (bare-metal, static VMs, Kubernetes nodes with a NAT gateway).

Notifications#

Tymo sends two kinds of notification: a down alert when a check misses its deadline, and a recovery notification when a previously-down check receives a ping. Recovery is automatic — you never need to manually close an incident.

Down alerts

The scheduler runs every minute. When a check's expectedNextPing timestamp has passed the grace period and no ping has arrived, the check transitions todown and an alert is dispatched.

Recovery notifications

Triggered immediately when a ping is received on a check that was previously in the down state. The check transitions back to up and a recovery email is sent.

Alert recipient

Alerts go to the alert emailconfigured in your organisation settings. If no alert email is set, they fall back to the organisation owner's account email.

Channel availability

ChannelStatusPlans
EmailLiveHobby + Pro
SMSIn developmentPro (when available)
WhatsAppIn developmentPro (when available)
You can enable SMS and WhatsApp toggles on a monitor today. They will fire automatically once the channels go live — no reconfiguration needed.

API reference#

The public ping endpoint is the only unauthenticated API surface. All other endpoints (creating/managing monitors, viewing logs) require a Bearer token and are documented in-app.

Ping endpoint

Request
GET  https://api.tymo.site/p/:token
POST https://api.tymo.site/p/:token

No authentication. No request body required.
StatusBodyMeaning
200{ "ok": true }Ping accepted. Monitor state updated.
200{ "ok": true }Check is paused — ping logged but state unchanged, no alert.
403{ "error": "..." }Source IP rejected by allowlist.
404{ "error": "..." }Token not found.
429{ "error": "..." }Rate limited — max 10 pings per 60 s per check.

Check status values

A monitor is always in one of four states:

StatusMeaning
pendingJust created — waiting for the first ping.
upLast ping was received on time.
downMissed the expected window + grace period. Alert sent.
pausedMonitoring suspended. Pings accepted but ignored.