init.Tasks openapi.json inittasks.com

a key, a curl, your first to-do

Quickstart

Five minutes, no OAuth, no registration.

1. Make a personal access token

In init.Tasks: Settings → account → encryption & devices → api keys → new key. Pick the scopes you need and an expiry.

You will see the key exactly once. It looks like this:

text
itk_7mQ2xLp9Va4Nk1Zr8Ts6Ye3Wu0Bd5Mg2Hj7Cq4Ln1Xv8

It carries your encryption key. Treat it like a password manager entry, not like an API key you paste into a chat.

2. Check it works

bash
curl -s https://api.inittasks.com/v1/me \
  -H "Authorization: Bearer $INITTASKS_TOKEN"
json
{
  "sub": "8Kd2mQ...",
  "scopes": ["todos:read", "todos:write"],
  "grant": { "id": "gr_4f2a", "kind": "pat", "clientId": null },
  "webhooks": { "disabled": 0 }
}

3. Create a to-do

bash
curl -s https://api.inittasks.com/v1/todos \
  -X POST \
  -H "Authorization: Bearer $INITTASKS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"title":"buy milk","whenDate":"2026-09-16","tags":["errands"]}'

The title is encrypted on the way in and decrypted on the way out. errands is created if it does not exist — you do not have to pre-register a vocabulary.

4. Read it back

bash
curl -s "https://api.inittasks.com/v1/todos?limit=5" \
  -H "Authorization: Bearer $INITTASKS_TOKEN"
json
{
  "data": [{ "id": "8E4F2A1B", "title": "buy milk", "whenDate": "2026-09-16", "tags": ["errands"] }],
  "next_cursor": null
}

Retrying safely

This is the part most integrations get wrong, so it is worth doing properly from the start.

A write that times out may still have succeeded. Retrying it without an Idempotency-Key creates a second to-do. With one, the server replays the original response instead.

bash
#!/usr/bin/env bash
# One key per logical operation — generated ONCE, reused by every retry.
KEY=$(uuidgen)

for attempt in 1 2 3 4 5; do
  response=$(curl -s -w '\n%{http_code}' https://api.inittasks.com/v1/todos \
    -X POST \
    -H "Authorization: Bearer $INITTASKS_TOKEN" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $KEY" \
    -d '{"title":"buy milk"}')

  status=$(printf '%s' "$response" | tail -n1)
  body=$(printf '%s' "$response" | sed '$d')

  case "$status" in
    2*) printf '%s\n' "$body"; exit 0 ;;
    429|5*)
      # Back off. `Retry-After` is on 429s; this doubles from one second.
      sleep $(( 2 ** (attempt - 1) ))
      ;;
    *) printf 'giving up: %s\n' "$body" >&2; exit 1 ;;
  esac
done

Three rules behind it:

  1. Generate the key once, outside the loop. A key generated per attempt defeats the whole mechanism — that is the actual bug this example exists to prevent.
  2. Retry only on 429 and 5xx. A validation_failed will fail identically forever.
  3. **Reuse the key with the same body.** A different body under the same key is a conflict, on purpose: it means two different operations were given the same name.

Next