Skip to documentation

CronRadar ingestion API

This is the complete customer-facing HTTP contract for telemetry and framework discovery. Official SDKs wrap these endpoints. The authenticated dashboard uses a separate management API that is not a supported customer integration surface.

  • Production v1 base URL: https://cron.life/api/v1
  • Machine contract: https://docs.cronradar.com/openapi.json
  • API key format: ck_app_{application}_{secret}
  • Content type for sync: application/json
  • Official SDK request timeout: 5 seconds

All endpoint paths below are relative to the v1 base URL. Version 1 is additive-only: existing fields, operations, and meanings remain supported, while new fields are optional. A breaking change requires a new major-version base URL and a documented overlap window during which both major versions operate.

The original unversioned routes remain compatibility aliases for deployed consumers: /ping/* maps to /api/v1/ping/*, /api/sync maps to /api/v1/sync, and /api/sync/status maps to /api/v1/sync/status. New integrations and official SDK releases use v1. No retirement date is assigned until consumer migration can be measured and a separate overlap window is announced.

Authentication

Telemetry supports two methods:

  1. URL path, the SDK-friendly primary form: /ping/{monitor_key}/{api_key}.
  2. HTTP Basic authentication: API key as the username and an empty password.

Bulk sync and sync status use HTTP Basic authentication only.

Use Basic authentication for manual diagnostics so the key does not enter shell history, proxy logs, or copied URLs:

curl --fail-with-body --silent --show-error \
  --user "$CRONRADAR_API_KEY:" \
  "https://cron.life/api/v1/sync/status"

API keys are stored as SHA-256 hashes. Plaintext is shown only when a key is created or rotated. Create a different CronRadar application and key for every deployment environment.

Telemetry endpoints

Every telemetry operation accepts GET and POST. POST is recommended for lifecycle events; GET remains supported for simple schedulers and compatibility.

EventURL-path authenticationBasic authenticationResult
Heartbeat/ping/{monitor_key}/{api_key}/ping/{monitor_key}Successful completion without duration tracking
Start/ping/{monitor_key}/{api_key}/start/ping/{monitor_key}/startExecution is running
Complete/ping/{monitor_key}/{api_key}/complete/ping/{monitor_key}/completeSuccessful terminal result and duration after start
Fail/ping/{monitor_key}/{api_key}/fail/ping/{monitor_key}/failFailed terminal result and immediate incident

Common parameters

ParameterLocationRequiredContract
monitor_keypathyesStable non-empty automation key, at most 200 characters; URL-encode it.
api_keypathpath-auth routes onlyApplication API key beginning with ck_app_.
schedulequeryonly to create a missing monitorStandard five-field cron expression. Supplying it makes the request self-registering.
gracePeriodquerynoGrace in seconds; minimum 60.
messagequeryfail onlyOptional failure context, at most 1,000 characters. Never send secrets, logs, job payloads, or customer records.
run_idquerynoOpaque execution identifier shared by start and terminal events, at most 128 characters. Enables truthful concurrent-run correlation.
attemptquerynoZero-based scheduler retry attempt. Diagnostic only; CronRadar never retries customer work.
Idempotency-KeyheadernoDuplicate-suppression key, at most 128 characters. Identity is monitor + key; a duplicate returns the original ping without reapplying state. Over-long values are ignored.
idempotency_keyquerynoHeader alternative; the header wins when both are present.

Bounded outcomes on completion

POST /complete may include at most five values under outcomes. Keys use lowercase letters, numbers, and underscores (maximum 64 characters); values must be finite JSON numbers or booleans. Configure matching expectations in automation settings first. Unconfigured keys are accepted but not stored. A configured key that is omitted fails the check.

curl --fail-with-body --silent --show-error --request POST \
  --user "$CRONRADAR_API_KEY:" \
  --header "Content-Type: application/json" \
  --data '{"outcomes":{"records_processed":842,"errors":0,"successful":true}}' \
  "https://cron.life/api/v1/ping/nightly-import/complete?run_id=import-2026-07-21"

CronRadar stores only observed-versus-expected numeric or boolean evidence. Never send job arguments, payloads, records, logs, secrets, tokens, or personal data. When an automation has configured outcome checks, heartbeat-only reports have no outcome body and therefore fail those checks as missing; use the lifecycle completion endpoint.

Self-register and record success

curl --fail-with-body --silent --show-error \
  --user "$CRONRADAR_API_KEY:" \
  --get "https://cron.life/api/v1/ping/daily-backup" \
  --data-urlencode "schedule=0 2 * * *" \
  --data-urlencode "gracePeriod=300"
{
  "status": "ok",
  "monitor": "daily-backup",
  "pingedAt": "2026-07-21T06:00:00Z",
  "warning": null
}

The first request creates the monitor when it is missing. Later requests may omit schedule, but continuing to send it preserves recovery after accidental deletion.

Full lifecycle

run_id="daily-backup-$(date +%s)-$$"

curl --fail-with-body --silent --show-error --request POST \
  --user "$CRONRADAR_API_KEY:" \
  --get "https://cron.life/api/v1/ping/daily-backup/start" \
  --data-urlencode "schedule=0 2 * * *" \
  --data-urlencode "run_id=$run_id"

if ./run-backup.sh; then
  curl --fail-with-body --silent --show-error --request POST \
    --user "$CRONRADAR_API_KEY:" \
    --get "https://cron.life/api/v1/ping/daily-backup/complete" \
    --data-urlencode "run_id=$run_id"
else
  exit_code=$?
  curl --fail-with-body --silent --show-error --request POST \
    --user "$CRONRADAR_API_KEY:" \
    --get "https://cron.life/api/v1/ping/daily-backup/fail" \
    --data-urlencode "run_id=$run_id" \
    --data-urlencode "message=Backup command exited with code $exit_code"
  exit "$exit_code"
fi

The shell example deliberately returns the original job exit code. Monitoring observes job behavior; it must not turn a failed job into a success. Use a different run_id for concurrent executions and reuse it across retry attempts; increment attempt when the scheduler exposes that number. Without a run ID, CronRadar preserves the individual events and labels any pairing as legacy or incomplete evidence.

Successful heartbeat, start, and complete requests return the common success response. Fail returns:

{
  "status": "failure_recorded",
  "monitor": "daily-backup",
  "recordedAt": "2026-07-21T06:00:12Z",
  "message": "Explicit failure recorded - alert triggered",
  "failureMessage": "Backup command exited with code 1"
}

Framework registry sync

POST /sync registers or reconciles a scheduler's complete recurring-job registry.

curl --fail-with-body --silent --show-error \
  --user "$CRONRADAR_API_KEY:" \
  --header "Content-Type: application/json" \
  --data '{
    "source": "internal-scheduler",
    "version": "1.0.0",
    "mode": "reconcile",
    "monitors": [
      {
        "key": "daily-backup",
        "name": "Daily backup",
        "schedule": "0 2 * * *",
        "gracePeriod": 300
      }
    ]
  }' \
  "https://cron.life/api/v1/sync"

Request contract

FieldRequiredContract
sourceyesStable integration identifier. It scopes authoritative reconciliation.
versionnoIntegration version for diagnostics.
modenoreconcile or omitted. The monitor list is authoritative for this source.
monitorsyesComplete current registry for this source. An empty valid list pauses all previously declared monitors for that source.
monitors[].keyyesStable normalized monitor key.
monitors[].namenoHuman-readable display name.
monitors[].schedulenoFive-field cron expression. Invalid schedules are reported per monitor.
monitors[].gracePeriodnoGrace in seconds, minimum 60.
monitors[].metadatanoBounded integration metadata. Do not include payloads or sensitive data.

Reconciliation behavior

  • Calls are idempotent for the same registry.
  • Monitor identity is application + key. Repeated keys in one registry are upserts where the final declaration wins; concurrent creates are retried as updates.
  • Existing keys update name, schedule, grace, and declaration time.
  • A valid authoritative request pauses keys from the same source that disappeared; it never deletes history.
  • Reappearing keys resume an automatic drift pause when plan capacity exists. A customer manual pause is preserved.
  • Any invalid discovered schedule prevents removal processing for that request.
  • Capacity overflow is recorded as created_plan_limited, paused, and returned as a per-monitor error. It does not create an overage or automatic upgrade.

Response contract

{
  "source": "internal-scheduler",
  "timestamp": "2026-07-21T06:00:00Z",
  "created": [{ "key": "daily-backup", "name": "Daily backup", "action": "created" }],
  "updated": [],
  "unchanged": [],
  "removed": [],
  "errors": [],
  "summary": {
    "total": 1,
    "created": 1,
    "updated": 0,
    "unchanged": 0,
    "removed": 0,
    "errors": 0
  }
}

Possible result actions are created, created_plan_limited, updated, unchanged, and paused_removed. HTTP 200 means the registry was processed; inspect errors for monitor-level rejection or capacity outcomes.

Sync status

GET /sync/status returns the authenticated application's non-drill monitors.

curl --fail-with-body --silent --show-error \
  --user "$CRONRADAR_API_KEY:" \
  "https://cron.life/api/v1/sync/status"
{
  "applicationId": "app_abc123",
  "totalMonitors": 1,
  "monitors": [
    {
      "monitorKey": "daily-backup",
      "name": "Daily backup",
      "schedule": "0 2 * * *",
      "gracePeriod": 300,
      "createdAt": "2026-07-21T05:55:00Z",
      "updatedAt": "2026-07-21T06:00:00Z",
      "lastPingAt": "2026-07-21T06:00:00Z",
      "status": "healthy"
    }
  ],
  "timestamp": "2026-07-21T06:01:00Z"
}

Status values are pending, healthy, warning, critical, and paused.

Errors and retry behavior

Error responses use this shape:

{
  "error": "MONITOR_NOT_FOUND",
  "message": "Monitor 'daily-backup' not found. Provide schedule parameter for auto-registration."
}
HTTPMeaningSafe action
400Invalid key, schedule, grace, or requestCorrect the request; do not retry unchanged.
401Missing, malformed, revoked, or invalid keyRotate or correct the secret; do not retry aggressively.
402A new active automation is not allowed by the current trial/planExisting automations still record; pause another automation or change plan.
404Application missing, or monitor missing without a scheduleAdd the schedule for self-registration or verify the application key.
429Per-key rate limit reachedWait for Retry-After; retry with bounded backoff and jitter.
500Unexpected service errorRetry with bounded backoff; never block the observed job indefinitely.

Telemetry limits are 60 requests per minute and 1,000 per hour per API key. Sync is limited to 10 requests per minute. Official SDKs catch network, timeout, 4xx, and 5xx failures and return control to user code; framework integrations reconcile again later.

Security and data boundary

Send monitor keys, schedules, opaque execution identifiers, retry numbers, lifecycle timestamps, and optional bounded failure context. Do not send job arguments, logs, traces, metrics streams, payloads, database records, access tokens, or personal data. The dashboard may store customer-owned HTTP(S) links to a log search, runbook, or source repository; CronRadar does not retrieve their content. Operational ownership, severity, environment, and alert destinations are lightweight management settings: an automation override wins, then its application default, then its team default. Acknowledging an active incident suppresses repeat escalation while detection and recovery notification remain active. Timed manual maintenance resumes monitoring automatically; plan and discovery pauses never do. All production endpoints use HTTPS.