This page offers endpoints that you can hit in order to do something, or get data.
You may also be interested in:
Create a sandbox user to start building and testing immediately—no sign-up, no auth token needed:
curl -X POST 'https://intend.do/api/v0/sandbox_user' \
-H 'Content-Type: application/json' \
-d '{"preset": "goals_intentions"}'
Returns an auth_token you can use right away. Sandbox users are temporary accounts that expire after 1 week—safe for testing irreversible actions like setting intentions. Full details below.
If you're just testing, or building something for yourself... use your personal auth token: (it'll show up here if you're logged in)
Append it to your request like this:
?auth_token=INTEND_AUTH_TOKEN
If you're building an application that others will use, you'll want to set up OAuth2.
Register your app at intend.do/apiclient/myapps. You'll get a client_id and client_secret.
We recommend storing these as environment variables or in a .env file:
INTEND_CLIENT_ID=ido_12345...
INTEND_CLIENT_SECRET=ido_sk_1234567...
https://intend.do/oauth/authorize?response_type=code
&client_id=CLIENT_KEY
&redirect_uri=http://example.com/REDIRECT_URI/
After the user approves, they'll be redirected to your redirect_uri with an authorization code:
http://example.com/REDIRECT_URI/?code=23rf87g2v0jij02f
curl -X POST https://intend.do/oauth/token \
-d grant_type=authorization_code \
-d code=CODE \
-d client_id=CLIENT_KEY \
-d client_secret=ido_sk_1234567... \
-d redirect_uri=http://example.com/REDIRECT_URI/
The response includes an access_token and refresh_token. Store both—the access token expires after one year, and you can use the refresh token to get a new one.
Include the access token in your requests:
curl https://intend.do/api/v0/u/me/userinfo.json \
-H "Authorization: Bearer ACCESS_TOKEN"
That's it! See the endpoint documentation below for what you can do.
See this javascript file for some documentation of the sorts of objects returned by the API.
Hi AI coding agents! Welcome :)
The premise: Intend is a to-do list app, but different from most to-do list apps. Where most such apps have a whole system for organizing a ton of things you're never actually going to do, Intend focuses you on only intentions you're going to do today. You can *draft* intentions for tomorrow, but you can't set them. Then at the end of the day, you review the day ("outcomes"), and set new ones afresh.
The daily flow: Each day, the user sets intentions. These are stored in today.core.list. The top uncompleted item is the user's current "next action" (nexa).
Intentions format: When POSTing to /api/v0/u/me/intentions, the raw field uses a specific text format: goalcode) intention text, one per line. For example: 1) Review pull requests. The goal code is a short identifier (like 1, 2) that maps to one of the user's goals. Use GET /api/v0/u/me/goals/active.json to see the codes. Items without a goal code are silently ignored.
More on intentions format:
For an intention that goes towards multiple goals, it can be: (eg if goal 2 is 'move more' and goal 3 is 'fun with friends'.) 2,3) go for a walk with John A user can have maximum 10 active goals, numbered 1-9 or 0. When goals are archived/completed/inactive, their code switches to a two-letter code, eg 'CT'. AB) upgrade node version on inactive project For an intention that doesn't go towards any goal, it's standard to use a "&" instead of the goal: &) laundry But you can actually use almost any code there, and it'll still be goal-less (item.gids=[]): $) fill out budget ❤️🔥) date night
Goals: Goals are the user's high-level areas of focus (e.g. "Health & Fitness", "Ship the Project"). Each goal has a code (used in text format), an _id (used internally in gids arrays), a color, and a privacy level. Goals have start/end dates and can be archived.
Item IDs (zid): Each intention/outcome has a zid (a short random string). Use zids with endpoints like completeById, nottodayById, setNowById, deferNext, etc. Get zids from today/core.json or newtabpage.json.
Day boundaries: A "day" doesn't end at midnight — it ends when the user goes to sleep. The dayStartTime setting (default: 5am) determines when one day ends and the next begins. Hours can be >24 (e.g. 25.5 = 1:30am, still counted as the previous day).
Timer: The timer supports pomodoros ("tomato" type, typically 25min, focus=1.2) and hourglass sessions ("sand" type, flexible duration). Timer ticking is handled by the frontend — the API can start/stop timers but the actual countdown requires a browser tab open.
Dates: Dates are in YYYY-MM-DD format (called "ymd"). Timestamps are JavaScript milliseconds, not Unix seconds.
Testing your work: This API has sandbox users—temporary, disposable accounts you can create with a single unauthenticated POST. This is relatively unusual for an API (though hopefully it'll become more common!). Use them! Create a sandbox user to test everything you build—post intentions, complete them, start timers, whatever—without worrying about messing up a real account. Don't ask the human for their auth token when you can just spin up a sandbox user in one request.
Great for testing—returns the user's name and username:
/api/v0/u/me/userinfo.jsonGets the user's list of goals, including each goal's current top priority. Returns {goals: [...], updated: timestamp}:
/api/v0/u/me/goals/active.json — currently active goals only/api/v0/u/me/goals/all.json — all goals, including archived/completedThe item below returns most of the data used to render the user's today page
/api/v0/u/me/today/full.json core ... GET /api/v0/u/me/today/core.json drafts ... GET /api/v0/u/me/today/drafts.json recent ... GET /api/v0/u/me/today/recent.jsonsettings ... GET /api/v0/u/me/today/settings.json timer ... GET /api/v0/u/me/today/timer.jsonThese return text/plain responses designed for humans and LLMs to read at a glance. The format may change slightly over time — if you need something reliably parseable, use the .json endpoints instead.
/api/v0/u/me/today/core.txt — today's intentions as a readable list. Each line includes a timestamp, the item's zid, status, and text:List for today (2026-03-06, last updated 2026-03-06 10:30:00 AM EST) - 09:15:00 a8f3k2x1 [ ] 1) Review pull requests - 09:15:00 b7d2m4y9 [X] 2) 30 min run in the park - 09:15:00 c1e5n8z3 [nvm] 3) Read chapter 5
/api/v0/u/me/today/timer.txt — timer status in plain English, e.g. Timer is ticking. Mode: pomo. Ends in 14m32s, at 3:45 PM EST/api/v0/u/me/goals/active.txt — one goal per line, e.g. Goal 1: Health & FitnessAdd new intention(s)
/api/v0/u/me/intentions ...parameters: {
raw (string: Intend data in intentions format, one item per line. returns 400 if no valid intentions found)ymd (string, optional: date in YYYY-MM-DD format. If omitted will use the current date based on user's dayStartTime. If in the past (ie a ymd before the one currently displayed on the today page) will just update the timeline. If tomorrow, will finish today & shift to "set intentions for tomorrow" mode. Does not play nice with dates further in the future—don't bother 😉)makeCurrent (optional boolean to put the new item(s) above all other not-yet-done items)makeAlmostCurrent (optional boolean to put the new item(s) immediately below the top not-yet-done item)response (optional: what to return. options are)
Post outcomes
/api/v0/u/me/outcomes ...parameters: {
raw (string: Intend data in outcomes format, one item per line. returns 400 if no valid data found)ymd (string, optional: date in YYYY-MM-DD format. if omitted will use the current date based on user's dayStartTime)response (optional: what to return. options are)
"today": the /today/full.json object"count": how many completed outcomes for the day (default)These endpoints were made for the New Tab Page extension and they therefore return the ntp json format:{nexa: {/* see format here */}, colors, goalName, darkTheme, remainingcount, remainingDenominator}
Get next action
/api/v0/u/me/newtabpage.jsonReturns the current next action with details, or indicates if there are no intentions set.
Complete a specific intention
/api/v0/u/me/completeById/zid(A zid is an id for an intention or outcome—any such item. You can get the zid from newtabpage.json or today/full.json or today/core.json)
Mark a specific intention as "not today"
/api/v0/u/me/nottodayById/zidEnter "now" mode
Both of these put the system into "now" mode (like the now page) where when you complete the current intention it shows empty space instead of whatever's next on the list. This mostly affects what thentp data returns.
/api/v0/u/me/setNowById/zid (enter "now" mode for this intention)/api/v0/u/me/notNow (enter "now" mode with no current intention)Move an intention
/api/v0/u/me/moveToCurrent/zid (move item to above all other not-yet-done items)/api/v0/u/me/deferNext/zid (move item to after the next outstanding item)/api/v0/u/me/deferLast/zid (move item to the end of the list)Pick a random item and set it as the next action
/api/v0/u/me/getRandomNextActionAppend to an intention
/api/v0/u/me/appendById/zid ...parameters: {
text (string. text to append to the intention)Retrieve past entries/days
/api/v0/u/me/timeline/entries.jsonlimit (maximum to pull; default = 21)startymd (the earliest date to include, in YYYY-MM-DD format)endymd (the latest date to exclude, in YYYY-MM-DD format)select (things to select separated by +. main options: intentions, outcomes, activity, goalCounts. default is all of these except activity)https://intend.do/api/v0/u/me/timeline/entries.json?startymd=2018-05-01&select=outcomes
Retrieve reviews
Each frequency has a remarks.json endpoint (the user's written reflections) and where available an overview.json endpoint (aggregated outcomes by goal).
/api/v0/u/me/reviews/:year/week/:weeknum/overview.json/api/v0/u/me/reviews/:year/week/:weeknum/remarks.jsonJan, Feb)
/api/v0/u/me/reviews/:year/:month/overview.json/api/v0/u/me/reviews/:year/:month/remarks.json/api/v0/u/me/reviews/:year/Q/:q/remarks.json (q = 1–4)/api/v0/u/me/reviews/:year/yearly/remarks.jsonCreating new work blocks ('dur', short for duration)
/api/v0/u/me/add_dur ...parameters: {
ty (string, required. "type" (must be either 'tomato' or 'sand'))min (number, required. "minutes" of duration. can be decimal)foc (number, optional. "focusedness". 20% = 0.2, 100% = 1. pomos default to 120% = 1.2)sCp (number, optional. "stamp completed". unix timestamp in millis. defaults)zidToAssignTo (string, optional. assigns the dur to the intention with this zid, returns 406 error if not found. returns {intention: ...} if found)These two old endpoints both return {sparePomos: n, spareDurs: [...]}
/api/v0/u/me/addpomo/api/v0/u/me/set_spare_pomos (takes a parameter n in the request body)The endpoints below control the actual timer itself. IMPORTANT: Note that the timer ticking logic is handled by the frontend on Intend, so while this system can let you start or stop pomodoros with a button, the actual tallying of pomodoros won't occur unless you have your today page or timer page open somewhere! Similarly, being in continuous/automatic mode will only cause the timer to continue if a tab is open.
All of them return the timer object, which looks like (click to view)
{
ticker: {
state: 'ticking',
mode: 'pomo',
endTime: 1522442719000,
continuous: true
},
extras: {
breakCount: 3,
spareTomatos: 4,
spareDurs: [{ // a list of duration items
min: 25, // length in minutes
ty: "tomato", // type ("tomato" or "sand")
src: "r", // source (t=today page timer, r=room, a=api, m=manual)
sCp: 1619231101181, // stamp completed
hCp: 19.42 // hour completed (hours since midnight of relevant day)
}],
lastPomoIncrementStamp: 1522437901064,
}
}
Get current timer
/api/v0/u/me/today/timer/allStart pomodoro
/api/v0/u/me/today/timer/startpomodoroduration (in minutes; if omitted, uses current setting)
Start break
/api/v0/u/me/today/timer/startbreakduration (in minutes; if omitted, uses current setting)
Start hourglass timer
/api/v0/u/me/today/timer/hourglassduration (in minutes; if omitted, uses 15 minutes)
Pause timer
/api/v0/u/me/today/timer/pauseUnpause timer
/api/v0/u/me/today/timer/unpauseCancel timer
/api/v0/u/me/today/timer/cancelCustom timer update
/api/v0/u/me/today/timer/ticker ...parameters: {
mode (either "pomo" or "hourglass")state (one of "inactive", "ticking", "breaking", "paused")endTime (required if ticking or breaking: numerical unix timestamp in millis)remainingSeconds (required if paused)
continuous (boolean; will stay the same if omitted)
Sandbox users are temporary, API-only accounts for safely testing the API—including irreversible actions like setting intentions—without affecting your real account. They expire after 1 week and are automatically cleaned up.
They're also great for automated tests—create a sandbox user in your test setup, run your assertions against the API, and delete it in teardown. No test fixtures or mocking needed.
⚠️ Privacy note: Sandbox user profiles are publicly viewable at their URL (e.g. /~sandbox_abc123.../). In practice this is similar to a Google Docs link set to "anyone with the link"—the long random username makes it effectively unguessable, but anyone with the URL can see the profile. In practice this will cause you zero issues; I mention it only to avoid someone going "hey! you exposed my data!" after cloning their real profile.
Create a sandbox user
/api/v0/sandbox_user No authentication required. Parameters: {
preset (string, optional. default: "goals". options:
"blank" — empty user, no goals, no intentions"goals" — 4 sample goals, no intentions for today (good starting point for most testing)"goals_intentions" — sample goals + 3 intentions already set for today"clone" — copies your goals and today's intentions to the sandbox user (requires authentication){ auth_token, username, preset, expiresAt }auth_token to make API calls as the sandbox user.Try it! No account needed:
curl -X POST 'https://intend.do/api/v0/sandbox_user' \
-H 'Content-Type: application/json' \
-d '{"preset": "goals"}'
Then use the sandbox user's auth_token to interact with the API:
curl 'https://intend.do/api/v0/u/me/goals/active.json?auth_token=SANDBOX_AUTH_TOKEN'
The sandbox user's profile is publicly viewable at /~sandbox_username/ so you can visually confirm what the API did.
List your sandbox users
/api/v0/sandbox_userDelete a sandbox user
/api/v0/sandbox_user/auth_tokenGet settings
/api/v0/u/me/apps/beeminder/settings.jsonPut settings
/api/v0/u/me/apps/beeminder/settings.json
intentionsBinary (beeminder goal slug for setting intentions at all)outcomesBinaryoutcomesPercentageroomPresenceweeklyReviewCountweeklyReviewCompletemonthlyReviewCountmonthlyReviewCompletequarterlyReviewCountquarterlyReviewCompletearbitrary (array of "beemind arbitrary things" items)beemgoal (string; beeminder goal slug for this arb match)trackWhat (string enum: ['exists' (intended)'d' (completed)'pd' (pomodoros completed)'totalMinutes''focusedMinutes''number''sum'goalid (Intend goalid, 'misc' if misc-only)textMatch (string; text or regex match)useRegex (boolean; true if textMatch is regex)isTextMatchInverse (boolean; true if counting only non-matches)starred (boolean; true means match only starred items)staked (boolean; true means match only items with $ at stake)multiplier (number; undefined means x1)paused (boolean; true means this beem arb doesn't fire)Use the question box on the right