Get started with doneyet
doneyet tells you the moment a scheduled job gets stuck, runs late, or fails — so you never find out the hard way. Pick the path that fits you below.
What is doneyet, in one sentence?
It's a smoke alarm for the work that runs in the background — your nightly exports, billing jobs, backups, and CI pipelines. doneyet watches each one. If a job goes quiet, overruns its normal time, or fails, you get a message. If it finishes cleanly, you see a green check.
Choose how you'd like to set it up
You can be running in a few minutes either way. Not sure? Start with No-code — you can always switch.
How doneyet works (the simple version)
Every job you care about has three moments. doneyet listens for them:
A few words you'll see
- Workspace
- Your team's private area in doneyet. Everything lives inside it.
- Workflow
- A job you run regularly, e.g. "Nightly Export". You set it up once.
- Run
- One single time that workflow actually ran (last night's export was one run).
- Alert
- A message to Slack, email, or your pager when something looks wrong.
Set it up from the dashboard
No terminal needed. Each step happens with clicks in the doneyet dashboard.
Create your free account
Go to app.doneyet.io and sign in. The free plan needs no credit card.
Create a workspace
Give it your team or company name. This is the home for everything you'll track.
Add your first workflow
Open Workflows → New workflow and fill in the short form:
• Name — what the job is, e.g. Nightly Export.
• Check-in grace — how long it may stay quiet before doneyet worries (e.g. 2 minutes).
• Expected duration — roughly how long it normally takes (e.g. 10 minutes). doneyet flags it if it runs much longer.
Connect the job that does the work
doneyet needs the job itself to say start / check-in / finish. If a teammate set up the job, hand them this page — they'll recognize it instantly. The dashboard shows a ready-to-paste snippet under your workflow's Connect tab, or send them to the Developer setup.
You don't have to understand the code — you just need someone to drop it into wherever the job runs.
Turn on alerts
Open Admin → Notifications, click Add channel, and pick Slack, email, PagerDuty, Microsoft Teams, or Opsgenie. Paste your Slack webhook or email and save. That's where stalls and failures will land.
Watch it on your board
Your dashboard now shows every workflow with a live status — green when done, amber when stalled, red when failed — plus how long each run took. No more digging through logs to ask "did the nightly job run?"
What an alert looks like
When a job stalls or fails, you get one clear message (not a flood — doneyet won't page you twice for the same flapping job):
Paste your workspace URL and token below and every command on this page fills in automatically. Values stay in your browser — nothing is sent anywhere.
The model
doneyet watches background work through a tiny contract your job calls around itself:
- start — register a run when the job begins. doneyet now expects it to finish within its grace + SLA window.
- heartbeat — ping while it works (every few seconds for long jobs). Go quiet past the grace window → a stall alert fires.
- finish — report succeeded or failed. No finish + no heartbeat → doneyet pages on-call.
A workflow is the named, recurring job (e.g. nightly-export); a run is one execution of it. Everything lives in a workspace (your org's boundary).
1Sign in & create a workspace
Open app.doneyet.io, sign in, and create a workspace. The free tier needs no card.
2Get an access token (PAT)
Programmatic access uses a Personal Access Token scoped to your workspace. Mint one from the dashboard under Admin → Access tokens, or with the CLI once you've signed in there:
# from the dashboard: Admin → Access tokens → New token
# or, with an existing admin token, mint a scoped service token:
dyt pat create --label ci-runner --ttl-days 90 --show
dyt pat revoke <id> + a fresh create.3Install the dyt CLI
Pre-built static binaries are on GitHub Releases — pick your platform:
# Linux amd64 (use dyt-linux-arm64 on ARM)
curl -fsSL -o dyt https://github.com/lucheeseng827/doneyet-cli/releases/latest/download/dyt-linux-amd64
chmod +x dyt && sudo mv dyt /usr/local/bin/
dyt --version
# macOS arm64 (use dyt-darwin-amd64 on Intel)
curl -fsSL -o dyt https://github.com/lucheeseng827/doneyet-cli/releases/latest/download/dyt-darwin-arm64
chmod +x dyt && sudo mv dyt /usr/local/bin/
dyt --version
# Windows amd64 (PowerShell)
curl.exe -fsSL -o dyt.exe https://github.com/lucheeseng827/doneyet-cli/releases/latest/download/dyt-windows-amd64.exe
.\dyt.exe --version
dyt --version prints the build; dyt health confirms it reaches your workspace.No installer? You can also call the REST API directly — see the interactive API reference.
4Point dyt at your workspace
dyt config set api-url https://app.doneyet.io
dyt login --admin-token - # paste your PAT at the hidden prompt
dyt health # → ok
dyt whoami # resolved config + server ping
Prefer env vars (CI)? Skip login and export instead:
export DONEYET_API_URL=https://app.doneyet.io
export DONEYET_ADMIN_TOKEN=<your-PAT>
5Register a workflow
Tell doneyet about the job once. heartbeat-grace-s is how long it may go silent before a stall fires; expected-duration-s drives overrun detection.
dyt workflow upsert \
--slug nightly-export \
--name "Nightly Export" \
--owner group:default/data \
--heartbeat-grace-s 120 \
--expected-duration-s 600
dyt workflow list # confirm it's there
6Wrap a run: start → heartbeat → finish
run start returns an id and a one-time run token used for heartbeat/finish on that run:
# start; capture the run id + run token
START=$(dyt run start nightly-export --output json)
RUN=$(echo "$START" | jq -r .id)
export DONEYET_RUN_TOKEN=$(echo "$START" | jq -r .token)
# … do the work, heartbeating along the way …
dyt run heartbeat "$RUN" --progress 50 --message "halfway"
dyt run heartbeat "$RUN" --progress 90
# report the outcome
dyt run finish "$RUN" --status succeeded
For a long job you don't want to instrument internally, let dyt heartbeat for you while the work runs:
START=$(dyt run start nightly-export --output json)
RUN=$(echo "$START" | jq -r .id); export DONEYET_RUN_TOKEN=$(echo "$START" | jq -r .token)
dyt run tail "$RUN" --interval 15 & # background auto-heartbeat
HB=$!
./your-actual-job.sh # the real work
kill $HB
dyt run finish "$RUN" --status $([ $? -eq 0 ] && echo succeeded || echo failed)
The exact same flow over HTTPS — the PAT starts the run, the returned run token authorizes heartbeat/finish:
BASE=https://app.doneyet.io/api/v1
PAT=<your-PAT>
# start a run → returns {"id":"...","token":"..."}
RESP=$(curl -fsS -X POST "$BASE/workflows/nightly-export/runs" \
-H "Authorization: Bearer $PAT" -H 'Content-Type: application/json' -d '{}')
RUN=$(jq -r .id <<<"$RESP"); RTOK=$(jq -r .token <<<"$RESP")
# heartbeat with the RUN token (note: progress_pct, not progress)
curl -fsS -X POST "$BASE/runs/$RUN/heartbeat" \
-H "Authorization: Bearer $RTOK" -H 'Content-Type: application/json' \
-d '{"progress_pct":50,"message":"halfway"}'
# finish
curl -fsS -X POST "$BASE/runs/$RUN/finish" \
-H "Authorization: Bearer $RTOK" -H 'Content-Type: application/json' \
-d '{"status":"succeeded"}'
Prefer to fill in real values and fire each call from your browser? Use the interactive API reference.
CI / cron examples
- name: Run nightly export (tracked by doneyet)
env:
DONEYET_API_URL: https://app.doneyet.io
DONEYET_ADMIN_TOKEN: ${{ secrets.DONEYET_TOKEN }}
run: |
START=$(dyt run start nightly-export --external-ref "$GITHUB_RUN_ID" --output json)
RUN=$(echo "$START" | jq -r .id); export DONEYET_RUN_TOKEN=$(echo "$START" | jq -r .token)
if make nightly-export; then dyt run finish "$RUN" --status succeeded;
else dyt run finish "$RUN" --status failed; exit 1; fi
# /etc/cron.d/nightly — wrap any command
0 2 * * * app DONEYET_API_URL=https://app.doneyet.io DONEYET_ADMIN_TOKEN=… \
bash -c 'S=$(dyt run start nightly-export -o json); R=$(jq -r .id <<<"$S"); \
export DONEYET_RUN_TOKEN=$(jq -r .token <<<"$S"); \
/opt/jobs/export.sh && dyt run finish "$R" --status succeeded || dyt run finish "$R" --status failed'
7Get alerted
Add a channel so stalls/failures reach you. Slack, PagerDuty, Opsgenie, email, or a signed webhook:
dyt notify channel create \
--kind slack \
--name oncall \
--target https://hooks.slack.com/services/T000/B000/xxxx
Then route events to it with a notification rule (dashboard Admin → Notifications, or POST /api/v1/notification-rules). Test it: start a run and send no heartbeats for heartbeat-grace-s + 30s — you should get exactly one alert.
Talk to the REST API directly
No CLI needed — the same flow over HTTPS. A workspace-scoped PAT is the bearer for admin calls; the run endpoints use the run token returned by start. The full surface is documented — and runnable — in the interactive API reference.
| Step | Call | Auth |
|---|---|---|
| Register workflow | POST /api/v1/workflows | PAT |
| Start run | POST /api/v1/workflows/{slug}/runs | PAT |
| Heartbeat | POST /api/v1/runs/{id}/heartbeat | run token |
| Finish | POST /api/v1/runs/{id}/finish | run token |
| List runs / overview | GET /api/v1/runs · /overview | read |
curl).Next steps
- See it live: open the dashboard — your runs, statuses, durations, and alert inbox.
- SLA windows: set
--expected-duration-sso a "successful" job that ran 3× too long still gets flagged. - Producers: shell wrapper, k8s sidecar, GitHub Actions step — open-source under Apache 2.0.
- API reference: the full, interactive REST API guide.
- Help: stuck? email support@doneyet.io.