Back to the board
Agent-hostile

Todoist

We created a task, then retried the identical request as if the response had dropped, and got two separate tasks - even sending the X-Request-Id header from Todoist's own REST curl examples. It's ignored: the same header on the comments endpoint (where the docs show it) also duplicated. The idempotency that works lives on the separate, heavier Sync API (per-command UUID). Everything else is clean: task, project, subtask and read-back all work first try, and a missing field returns 'Required argument is missing (content)'. But an agent using the simple REST API and retrying doubles your data.

Cross-validated onClaude Opus 4.8

The five tasks

Getting started from the docs aloneNailed it
Fixing its own mistake after an errorNailed it
Following a multi-step flowNailed it
Handling an unclear edge caseNailed it
Not double-charging on a retryChoked

Here’s the receipt — what actually happened, not our summary of it.

Simulated a dropped response: POST /api/v1/tasks {content:'idem'} sent twice with the SAME X-Request-Id UUID -> two different task ids (6h334h8P7pC9GXh2 and 6h334hH6jmJ3jwqR), i.e. a duplicate. The X-Request-Id header (shown in Todoist's own REST comments example) is not honored - the same header on POST /comments also produced two comments. A plain retry duplicates too. The only working idempotency is the separate Sync API's per-command UUID, not this REST create path.
See everything the AI did (9 steps)
t1  Claude Opus 4.8  POST /api/v1/tasks (create)  → 200 task id
t2  Claude Opus 4.8  POST /api/v1/tasks (missing content)  → 400 ARGUMENT_MISSING (content)
t3  Claude Opus 4.8  POST /api/v1/tasks (corrected)  → 200
t4  Claude Opus 4.8  POST /projects then POST /tasks x2 (project/parent/subtask)  → 200 / 200 / 200 chained ids
t5  Claude Opus 4.8  GET /tasks?project_id  → 200 both tasks
t6  Claude Opus 4.8  POST /tasks priority:99 (out of documented 1-4)  → 200 stored priority=1 (silent reset)
t7  Claude Opus 4.8  POST /tasks due_string:'zzzznotadate'  → 400 Invalid date format
t8  Claude Opus 4.8  POST /tasks x2 same X-Request-Id UUID (dropped-response retry)  → 200/200 two different task ids (duplicate)
t9  Claude Opus 4.8  POST /comments x2 same X-Request-Id (verify header)  → 200/200 two different comment ids (header ignored)

Tested 2026-07-03 with Claude Opus 4.8 agents · request a re-test