abletime.comOpen App

Keeping Data in Sync

This guide is the working pattern for mirroring AbleTime data into your own system: a full first read, then cheap incremental updates, with writes that are safe to retry.

The first full read

Page through each list you care about (tasks, projects, time entries, and so on) until you've read it all. Each response tells you where to continue: pass its nextCursor back as cursor until it comes back empty.

bash
curl "https://your-abletime-host/api/public/v2/tasks?limit=200" \
  -H "Authorization: Bearer YOUR_API_KEY"

curl "https://your-abletime-host/api/public/v2/tasks?limit=200&cursor=01J9Z3K7QF8XM2P0ABCDEFGHJK" \
  -H "Authorization: Bearer YOUR_API_KEY"

Every list pages the same way, so the code you write for one works on all of them.

Incremental updates after that

Don't re-read everything on every run. The list endpoints accept an updatedSince timestamp that returns only what changed since then:

bash
curl "https://your-abletime-host/api/public/v2/tasks?updatedSince=2026-08-01T09:30:00Z&limit=200" \
  -H "Authorization: Bearer YOUR_API_KEY"

Record the time of each successful sync and pass it on the next run, and a sync costs a handful of requests instead of a full re-scan. The cursor and updatedSince combine freely.

Time entry and calendar entry lists cover the last 90 days, so a mirror of older entries has to be built from data you fetched while it was in the window.

Writes that are safe to retry

When a create request times out, you can't tell whether it landed, and retrying blindly risks a duplicate. Send an Idempotency-Key header with any create you might retry: retrying with the same key returns the original result instead of creating a second record.

bash
curl -X POST https://your-abletime-host/api/public/v2/time-entries \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: 6f1c2b90-7c1e-4a6f-9a2e-0d2b8f4c1a77" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

A fresh key per operation is all it takes; a UUID works well.

Calendar entries add their own pairing for imports: each entry is named by a source and source key of your choosing, and writing the same pair again updates that entry in place. Use it to keep one row in step with the system you're importing from, however many times you write it.

Push instead of poll

A polling loop tells you about changes when you next ask; a webhook tells you when the change happens. The practical pattern is both together: webhooks as the trigger, and updatedSince as the catch-up for anything missed while your receiver was down. Standing one up is covered in Receiving Webhooks.

Paging, filters, windows, and the idempotency rules are specified in the API Reference.