Skip to content

fix(docs): call Todoist API v1 directly in the Todoist example script - #1814

Merged
chhoumann merged 3 commits into
masterfrom
fix/todoist-example-api-v1
Sep 26, 2026
Merged

chhoumann merged 3 commits into
masterfrom
fix/todoist-example-api-v1

Conversation

@chhoumann

@chhoumann chhoumann commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Summary

The Fetch Tasks From Todoist example script no longer works:

  • It called app.plugins.plugins["todoist-sync-plugin"].api.getTasks() / getProjects() / getSections() / closeTask(). In the current Todoist plugin (2.6.0), plugin.api is an internal wrapper, and none of those methods exist on it.
  • Todoist's REST v2 API now returns 410 Gone. Checked against a real account: GET /rest/v2/projects → 410, GET /api/v1/projects → 200.

The script now calls the Todoist API v1 directly through obsidian.requestUrl, so it no longer depends on another plugin's internals.

  • Token: a QuickAdd script setting of type secret (id: "todoist-api-token"), stored in Obsidian SecretStorage. Only a secretRef goes into data.json.
  • Endpoints: GET /tasks, /projects, /sections, following next_cursor pagination with limit=200, and POST /tasks/{id}/close.
  • Exports: SelectFromAllTasks, GetAllTasksFromProject and GetAllTasksFromSection are kept. The script also exports entry, which asks which of the three to run.
  • Output: unchanged Tasks-plugin format, - [ ] <content> 📅 YYYY-MM-DD. Due dates for tasks with a fixed time zone (UTC …Z in v1) are converted to the local date.
  • Completion: completing imported tasks is now a checkbox setting, Complete imported tasks in Todoist (default on, matching the old behavior), instead of "remove the closeSelectedTasks call". Recurring tasks are formatted before they are closed.
  • Close failures: each task is closed independently. A failed close never drops tasks from the note; the script shows "Could not complete N of M imported tasks in Todoist; they are still open there."
  • Old bugs fixed: closes were fire-and-forget (forEach(async …)), GetAllTasksFromSection called closeSelectedTasks without app, selection matched by substring, and a cancelled section picker crashed.

Docs page

The page now covers:

  • Prerequisites: a Todoist API token. The Todoist plugin is no longer needed.
  • Setup: add the script to a macro, set the token through the gear, and choose the export from the Capture format.
  • Completion: a caution callout replaces the old IMPORTANT note, and there is a Troubleshooting section.
  • Choosing an export: {{MACRO:Todoist::GetAllTasksFromProject}} instead of naming the macro command Script::Export. A command named Script::Export drills straight to the function, so the gear can't show the script's settings and the token can't be set.
  • Images: the old Todoist-GetAllTasksFromProject.png (which showed that :: command naming) is replaced by a screenshot of the new settings. The #installation-video anchor that other pages link to is kept, with a note that the video predates the token setting.

Proof: real Obsidian 1.13.7, real Todoist account

Setup: an isolated e2e vault (pnpm run start:e2e-obsidian) with made-up content. The token was entered through the real gear modal; afterwards data.json held only {"__quickaddSecret":true,"secretRef":"quickadd-user-script-todoist-script-todoist-api-token"}.

Todoist fixture: a temporary project "QuickAdd Demo (temporary)" with sections Errands and Reading, and 5 made-up tasks: date-only, no date, a fixed-time-zone datetime, and none. After each run, a SHA-256 fingerprint of every other project, section and task (IDs, names, content, checked, due, updated_at) was compared with the pre-test fingerprint.

Run (quickadd:run … ui verify) Note received Todoist afterwards Other data fingerprint
{{MACRO:Todoist::GetAllTasksFromSection}} → Errands - [ ] Buy oat milk 📅 2031-01-15
- [ ] Return library books
those 2 completed unchanged
{{MACRO:Todoist::SelectFromAllTasks}} → 1 task ticked - [ ] Read chapter 3 of the demo novel 📅 2031-02-03 (v1 returned 2031-02-03T08:30:00Z) that 1 completed unchanged
{{MACRO:Todoist}} → export picker → GetAllTasksFromProject, completion unticked in the gear UI - [ ] Water the plants 📅 2031-03-20
- [ ] Plan picnic
both still open unchanged
{{MACRO:Todoist::GetAllTasksFromProject}}, completion on same 2 lines both completed unchanged
Same, on the now-empty project nothing: notice No tasks in 'QuickAdd Demo (temporary)'., QuickAdd effect: "unchanged" — unchanged
No token ok:false … Add your Todoist API token in the Todoist script's settings … no request made —
Wrong token ok:false, "error":"Todoist rejected the API token (HTTP 401). Check the token in the Todoist script's settings." — —

Every successful run returned "ok":true,"verified":true,"effect":"changed","file":"Todoist Inbox.md".

Final commit re-run: after the review fixes, the fixture was recreated and {{MACRO:Todoist::GetAllTasksFromProject}} was run again with the final script. The note received all 5 demo tasks with their due dates, all 5 were completed, and the other data fingerprint was unchanged.

Cleanup: the temporary project was deleted after each session. GET /api/v1/projects/<temp id> → 404; a projects scan found 0 projects with that name; and the fingerprint of all other data matched the pre-test value (e102f21b05e0aeed before and after).

Screenshots are from the throwaway vault. Pickers were filtered to the demo project before each capture, so no real account data appears.

Script settings (gear) Export picker ({{MACRO:Todoist}})
settings export picker
Section picker Select tasks
section picker select

Resulting note. Newest captures are on top; the Water/Picnic pair appears twice because the first project run had completion off.

result note

Tests

  • New tests/examples/todoistScript.test.ts runs the script against a fake v1 server (2-item pages). It covers pagination, per-project and per-section filtering, duplicate task names, a close failing mid-batch, local conversion of UTC due dates (pinned to Asia/Tokyo, where 23:30Z is the next day), completion on and off, the entry picker, and missing and rejected tokens.
    • Mutation-checked: dropping pagination fails 5 tests, dropping the UTC→local conversion fails 1, always closing fails 1, and stopping at the first failed close fails 1.
  • pnpm run test: 448 files, 5819 tests pass. pnpm run build-with-lint and pnpm run check pass. main.js is unchanged.
  • Docs: pnpm run build and python3 scripts/check-links.py → 0 problems across 52 pages. The rendered page was inspected locally.

Release / migration impact

Docs and example only; no plugin code changes. Users of the old script need to download the new one and paste a Todoist API token in the script's settings. The Todoist plugin is no longer required.

Note

Call Todoist API v1 directly in the Todoist example script

  • Replaces the Obsidian Todoist-plugin integration with a direct API client (createTodoist) that authenticates with a secret token and follows paginated list endpoints (page size 200)
  • Adds three selectable import modes: all tasks, by project, and by section. Tasks with identical content stay distinct via indexed checkbox labels
  • Adds script settings for the API token (secret) and whether imported tasks are completed in Todoist; completion is on by default and can be disabled
  • Formats due dates from the Todoist due object, converting UTC values to local dates, and emits the Tasks-plugin date marker instead of the old calendar symbol
  • Adds a Vitest suite with an in-memory Todoist API double covering pagination, duplicate-name selection, timezone handling, partial close failures, and token errors; docs now describe direct-token setup and troubleshooting
  • Behavioral Change: the script no longer depends on the Obsidian Todoist plugin — existing users must configure a Todoist API token in QuickAdd script settings. A failed close request no longer aborts remaining completions, and the capture output is preserved

Macroscope summarized b0367ed.

Summary by CodeRabbit

  • New Features
    • Import tasks from Todoist by selecting from all tasks, a project, or a section.
    • Imported tasks can be completed in Todoist automatically; this is enabled by default and can be turned off.
    • Due dates are included in imported task checklists.
  • Documentation
    • Updated setup instructions to cover API token configuration, import options, and troubleshooting.

The example relied on the Todoist plugin's internal api object, which no
longer exposes getTasks/getProjects/getSections/closeTask, and Todoist's
REST v2 API now returns 410 Gone. The script now calls
https://api.todoist.com/api/v1 with a token from a QuickAdd secret
setting, follows cursor pagination, and makes completing imported tasks
an opt-out checkbox.

Amp-Thread-ID: https://ampcode.com/threads/T-01a0df6d-45d0-75e7-8b10-3ce80c6ed75d
Co-authored-by: Christian Bager Bach Houmann <christian@bagerbach.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-26T21:10:30.817738Z 7a55976 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 79809fac-e622-456e-95bb-0abf54fa26da

📥 Commits

Reviewing files that changed from the base of the PR and between 82fcd33 and b0367ed.

⛔ Files ignored due to path filters (2)
  • docs/src/content/docs/docs/Images/Todoist-GetAllTasksFromProject.png is excluded by !**/*.png
  • docs/src/content/docs/docs/Images/Todoist-ScriptSettings.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • docs/public/scripts/TodoistScript.js
  • docs/src/content/docs/docs/Examples/Capture_FetchTasksFromTodoist.md
  • tests/examples/todoistScript.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 1 remain after this review.


📝 Walkthrough

Walkthrough

The Todoist script now uses authenticated Todoist API v1 requests to retrieve paginated tasks, projects, and sections. It offers three import modes, formats task dates, and can complete imported tasks. The guide and tests cover the updated setup and import behavior.

Changes

Todoist task import

Layer / File(s) Summary
API configuration and client
docs/public/scripts/TodoistScript.js, tests/examples/todoistScript.test.ts, docs/src/content/docs/docs/Examples/Capture_FetchTasksFromTodoist.md
The script adds API token and completion settings, an entry point, and an authenticated API v1 client that follows pagination cursors. The tests cover setup and token errors. The guide updates API token setup and troubleshooting.
Task selection and import
docs/public/scripts/TodoistScript.js, tests/examples/todoistScript.test.ts, docs/src/content/docs/docs/Examples/Capture_FetchTasksFromTodoist.md
The import modes select tasks from all tasks, a project, or a section. The script formats task dates and can close selected tasks sequentially, while retaining output when closes fail. The tests and guide cover selection, completion, and task formatting.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant QuickAdd
  participant TodoistScript
  participant TodoistAPI as Todoist API v1
  QuickAdd->>TodoistScript: Choose import mode and tasks
  TodoistScript->>TodoistAPI: Fetch tasks, projects, or sections
  TodoistAPI-->>TodoistScript: Return requested data
  TodoistScript-->>QuickAdd: Return formatted tasks
  opt Completion enabled
    TodoistScript->>TodoistAPI: Close selected tasks sequentially
  end
Loading

Merge Risk: ⚪ Minimal · up to b0367

The Todoist import changes are ready to merge after normal checks; rejected tokens receive the intended error message.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to b0367

The new integration has useful token-storage and failure-handling controls, but it can complete Todoist tasks before their note content is saved. An interrupted import may therefore need manual recovery.

Retained concerns

  • Medium · reliability · inferred: Task closes are awaited before imported text is returned to the note consumer. If execution stops or note persistence fails after a successful close, the task can be completed remotely without appearing in the note; no reconciliation step is visible in the script. The baseline already initiated closes before returning, but did not await their completion.
Security review details

Security Blast Radius

  • inferred — The independently affected scope is a user’s configured Todoist account and local import: project and section modes can select every retrieved task in that grouping, and the token enables the script’s reads and closes. No cross-account or hosted-service path was established.

Trust Boundaries and Controls

  • observed — Credential storage crosses from a local secret reference into ephemeral script settings and then a Todoist bearer header. A missing token or unresolved reference stops execution, and HTTP authorization failures are reported without placing the token in the scripted error text.

Resilience and Maintainability Implications

  • inferred — Per-task error handling contains an explicit close failure, but it cannot reconcile a successful remote close with a later interrupted or failed note write. The downstream persistence behavior remains unverified.

Hardening Proposals

  • proposed — Consider a recoverable import-and-complete workflow or explicit reconciliation guidance for tasks closed before note persistence, and document how users clear the local token when retiring the example.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 2 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: updating the Todoist example script to call Todoist API v1 directly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit taps the token key,
Then gathers tasks from page to page.
It marks each date beside the task,
And closes them when settings ask.
If one close fails, the rest proceed,
The note still holds the captured seed.

Comment @coderabbitai help to get the list of available commands.

Comment thread docs/public/scripts/TodoistScript.js Outdated
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Deploying quickadd with  Cloudflare Pages  Cloudflare Pages

Latest commit: b0367ed
Status: ✅  Deploy successful!
Preview URL: https://d6ea01ed.quickadd.pages.dev
Branch Preview URL: https://fix-todoist-example-api-v1.quickadd.pages.dev

View logs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a559767e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/public/scripts/TodoistScript.js Outdated
cursoragent and others added 2 commits September 26, 2026 21:13
If a close POST fails after earlier tasks already completed, still return
the formatted output with a notice so QuickAdd writes the note instead of
dropping the capture. Covers Macroscope High and Codex P1 on #1814.

Co-authored-by: Christian Bager Bach Houmann <christian@bagerbach.com>
Close each imported task independently instead of stopping at the first
failed request, and report exactly how many are still open in Todoist.
The capture still gets every imported task.

Amp-Thread-ID: https://ampcode.com/threads/T-01a0df6d-45d0-75e7-8b10-3ce80c6ed75d
Co-authored-by: Christian Bager Bach Houmann <christian@bagerbach.com>
@chhoumann
chhoumann merged commit 1482aab into master Sep 26, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants