Documentação

O CronObserver monitora jobs agendados por meio de check-ins. Você envia um POST quando o job termina, e nós te avisamos se algo atrasar ou falhar.

Referência HTTP completa: referência da API (OpenAPI).

Visão geral

  1. Crie um monitor e copie o token dele.
  2. Quando o job terminar, envie um check-in para a URL do monitor.
  3. Se o check-in não chegar no horário, você recebe alertas.

Endpoint de check-in

POST https://cronobserver.com/checkin/<token>

Use o token do monitor ou um token de integração. Check-ins aceitos retornam 204. GET e HEAD também funcionam, então qualquer ferramenta de ping HTTP consegue fazer check-in.

  • 401 quando o token de integração expirou.
  • 404 quando o token não existe.
  • 4xx para payloads JSON inválidos.
curl -i -X POST https://cronobserver.com/checkin/<token>
# or simply
curl -fsS https://cronobserver.com/checkin/<token>

Início, sucesso e falha

Reporte cada etapa de uma execução. Os três aceitam POST, GET e HEAD.

  • /checkin/<token>/start: a execução começou. Não muda o estado do monitor.
  • /checkin/<token>: a execução deu certo. Se vier depois de um start, a duração é registrada.
  • /checkin/<token>/fail: a execução falhou. Você recebe um alerta na hora, com exitCode e message, sem esperar o intervalo e a tolerância.

Envie o mesmo runId (no corpo ou como ?rid=) no início e no fim para ligar os dois quando as execuções se sobrepõem. Sem ele, o fim fecha a execução aberta mais recente.

Defina a Duração máxima no monitor (maxRuntimeSeconds na API): uma execução que começou e não deu certo nem falhou dentro desse tempo gera um alerta de travada, uma única vez.

URL=https://cronobserver.com/checkin/<token>
RID=$(date +%s)
curl -fsS "$URL/start?rid=$RID"
if run-job; then
  curl -fsS "$URL?rid=$RID"
else
  curl -fsS "$URL/fail?rid=$RID&exitCode=$?"
fi

Payload opcional

Você pode enviar um payload JSON com detalhes da execução. Ele fica guardado com o check-in e ajuda a analisar falhas. "status": "failed" no check-in simples conta como /fail, então este é um relato de falha:

curl -X POST https://cronobserver.com/checkin/<token> \
  -H "Content-Type: application/json" \
  -d '{
    "status": "failed",
    "exitCode": 1,
    "message": "Timeout calling the payments API",
    "metadata": { "host": "worker-01" }
  }'

runId, exitCode e message ligam a execução e explicam uma falha. Para agentes de IA e jobs de LLM:

ChaveExemploSignificado
model"claude-opus-5-5"Modelo usado na execução
tokens_in / tokens_out18234 / 2100Tokens consumidos
cost_usd0.42Custo da execução
items_processed37O que a execução produziu (linhas, tickets, e-mails)
eval_score0.91Sua própria nota de qualidade, de 0 a 1

Todas as chaves são opcionais e ficam guardadas com a execução. Sozinhas, elas não disparam alertas.

curl -X POST https://cronobserver.com/checkin/<token> \
  -H "Content-Type: application/json" \
  -d '{"runId":"nightly-42","model":"claude-sonnet","tokens_in":18200,"tokens_out":2400,"cost_usd":0.09,"items_processed":120,"eval_score":0.94}'

API REST (v1)

Gerencie monitores pelo código, pelo CI ou por um agente de IA. Crie uma chave de API em Configurações → Chaves de API. Cada chave pertence a uma organização e tem escopos: read, write e checkin. A chave aparece uma única vez; guardamos só o hash.

# list monitors
curl -s https://cronobserver.com/api/v1/monitors \
  -H "Authorization: Bearer $CRONOBSERVER_API_KEY"

# create a monitor that expects a run every day at 21:00 in São Paulo, with 30 minutes of grace
curl -s -X POST https://cronobserver.com/api/v1/monitors \
  -H "Authorization: Bearer $CRONOBSERVER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "nightly-summary-agent", "interval": {"type": "cron", "cronExpression": "0 21 * * ? *", "timezone": "America/Sao_Paulo"}, "graceMinutes": 30, "maxRuntimeSeconds": 1800}'
EndpointEscopoO que faz
GET /v1/monitors · GET /v1/monitors/{id}readLista ou lê monitores
POST /v1/monitors · PATCH · DELETE /v1/monitors/{id}writeCria, atualiza, apaga
GET /v1/monitors/{id}/eventsreadCheck-ins, falhas e alertas, paginados
GET /v1/monitors/{id}/explainreadPor que o monitor está no estado atual
POST /v1/monitors/{id}/pause · /resumewritePausa e retoma
POST /v1/monitors/{id}/mute · /unmutewriteSilencia alertas (opcionalmente até uma data)
POST /v1/monitors/{id}/checkin · /checkin/start · /checkin/failcheckinReporta uma execução pelo id: sucesso, início ou falha
GET /v1/incidents · POST /v1/incidents/{id}/ackread · writeIncidentes abertos e confirmação

Referência completa: OpenAPI 3.1 · documentação interativa. Os limites do plano valem na API exatamente como no painel.

Alertas no Telegram

  • Telegram: abra o @CronObserverBot (t.me/CronObserverBot) no Telegram e envie /start (num grupo, adicione o bot antes e envie /start lá). O bot responde com o ID do chat. Cole em ID do chat do Telegram no monitor (telegramChatId na API). Para um canal, adicione o bot como administrador e cole o @usuario do canal; guardamos o ID numérico dele.
  • Ele recebe os mesmos alertas do Slack e do Teams: atraso, execução com falha ou travada e recuperação. Também pode ser passo de uma política de escalonamento. Não conta na cota diária de e-mail. Plano Orbital.

Agendamentos cron e fusos horários

Monitores cron usam a sintaxe de cron da AWS e seguem o fuso horário do monitor (UTC por padrão). Na API, defina interval.timezone com um nome IANA: {"type":"cron","cronExpression":"0 9 * * ?","timezone":"America/Sao_Paulo"} espera o job às 09:00 em São Paulo. Um monitor novo passa a ser esperado no momento em que é criado: se o job nunca fizer check-in, você recebe um alerta depois da primeira janela mais a tolerância.

Exemplos rápidos

JavaScript (Node.js)

await fetch("https://cronobserver.com/checkin/<token>", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ status: "success", message: "Job finished" })
});

TypeScript

type CheckinPayload = {
  status: "success" | "failed";
  message: string;
  metadata?: Record<string, string | number | boolean>;
};

const payload: CheckinPayload = {
  status: "success",
  message: "Report generated",
  metadata: { reportId: 42 }
};

await fetch("https://cronobserver.com/checkin/<token>", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(payload)
});

Go

payload := []byte(`{"status":"success","message":"Job completed"}`)
req, _ := http.NewRequest("POST", "https://cronobserver.com/checkin/<token>", bytes.NewBuffer(payload))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
client.Do(req)

Rails

require "net/http"
require "json"

uri = URI("https://cronobserver.com/checkin/<token>")
Net::HTTP.post(uri, { status: "success", message: "Job ok" }.to_json, "Content-Type" => "application/json")

Java

HttpClient client = HttpClient.newHttpClient();
String payload = "{\"status\":\"success\",\"message\":\"Job completed\"}";
HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://cronobserver.com/checkin/<token>"))
  .header("Content-Type", "application/json")
  .POST(HttpRequest.BodyPublishers.ofString(payload))
  .build();
client.send(request, HttpResponse.BodyHandlers.discarding());

Python (requests)

import requests
requests.post(
  "https://cronobserver.com/checkin/<token>",
  json={"status": "success", "message": "Job executed"}
)

Integrações

GitHub Actions

Agende o workflow e envie um check-in no fim do job. Guarde o token em secrets.

- name: CronObserver check-in
  if: success()
  run: curl -fsS --retry 3 -X POST "$CRONOBSERVER_CHECKIN_URL"
  env:
    CRONOBSERVER_CHECKIN_URL: ${{ secrets.CRONOBSERVER_CHECKIN_URL }}

GitLab CI

Use os agendamentos do GitLab e um stage final de notificação para enviar o check-in.

cronobserver:checkin:
  stage: notify
  image: curlimages/curl:8.11.1
  script:
    - curl -fsS --retry 3 -X POST "$CRONOBSERVER_CHECKIN_URL"
  only:
    - schedules

Kubernetes CronJob

Guarde a URL em um Secret e injete no container do CronJob. O check-in acontece depois que o script termina. Sua imagem precisa ter curl (alpine: apk add --no-cache curl).

env:
- name: CRONOBSERVER_CHECKIN_URL
  valueFrom:
    secretKeyRef:
      name: cronobserver-checkin
      key: url
...
command: ["sh", "-c", "run-job && curl -fsS --retry 3 -X POST $CRONOBSERVER_CHECKIN_URL"]

AWS Lambda

Use um agendamento do EventBridge para invocar a função e envie um check-in no fim.

await fetch(process.env.CRONOBSERVER_CHECKIN_URL, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ status: "success", message: "Lambda ok" })
});

Docker Compose

Defina a URL como variável de ambiente e rode o curl depois que o job terminar. Sua imagem precisa ter curl (alpine: apk add --no-cache curl). O $$ impede que o Compose substitua a variável antes de o container subir.

services:
  job:
    image: curlimages/curl:8.11.1
    environment:
      - CRONOBSERVER_CHECKIN_URL=https://cronobserver.com/checkin/<token>
    command: sh -c "run-job && curl -fsS --retry 3 -X POST $$CRONOBSERVER_CHECKIN_URL"

Tokens e segurança

Há dois tipos de token para check-ins:

  • Token do monitor: permanente e ligado ao monitor.
  • Token de integração: temporário, revogável e com validade (formato it_*). Ideal para CI/CD e ambientes compartilhados.

Guarde os tokens em secrets ou variáveis de ambiente e evite comitá-los em repositórios.

Checks sintéticos

Disponível no Orbital (US$ 1,90/mês). No plano Free, os alertas são só por e-mail.

Checks sintéticos são sondas ativas executadas pelo CronObserver. Em vez de esperar um check-in, o sistema envia requisições HTTP para uma URL configurada e valida se a resposta é a esperada.

  • Tipos suportados: httpGet e httpPost.
  • Validação pelo status esperado (por exemplo, 200). Se o status for diferente, o check falha.
  • Controle de timeout e medição do tempo de resposta.
  • Proteção contra SSRF: bloqueia IPs privados e localhost (allowlist opcional).

Quando um check sintético falha, o monitor registra o erro e envia alertas. Quando ele se recupera, um evento de recuperação também é enviado.

Monitoramento simples e confiável para jobs agendados.
Integrações de observabilidade

Envie alertas para Datadog, Dynatrace, New Relic e Sentry

Configure as integrações por monitor. Os segredos são só de escrita, ficam criptografados e nunca são devolvidos pela API.

Disponível no Orbital (US$ 1,90/mês). No plano Free, os alertas são só por e-mail.

Obrigatório quando ativado

  • Datadog: apiKey
  • Dynatrace: baseUrl + apiToken
  • New Relic: apiKey (região opcional)
  • Sentry: dsn

Detalhes do payload

  • Tipo de alerta: atraso, escalada ou limite.
  • Só metadados do monitor (sem payloads nem tokens).
  • Os eventos incluem horários e o contexto do alerta.