Intend API 0.5.0 (alpha)

If you're wanting to use it in a production application, let us know so we can make sure that it's going to be stable enough for your purposes.

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=AUTH_TOKEN

If you're wanting to set up an application that others can use, or release your own chrome extension, you'll want to create an OAuth2 application.

OAuth2 Instructions

Step 1: make an Intend API client here: https://intend.do/apiclient/new


Step 2: Send the user here to authorize:

https://intend.do/oauth/authorize?response_type=code
&client_id=CLIENT_KEY
&client_secret=CLIENT_SECRET
&redirect_uri=http://example.com/REDIRECT_URI/

If you're making a Chrome extension, you'll want to use

chrome.identity.launchWebAuthFlow(
  {'url': THE_ABOVE_URL, 'interactive': true},
  function callback () {}
);

This will hit your redirectUri with a code as a GET param, like

http://example.com/REDIRECT_URI/?code=23rf87g2v0jij02f

Step 3: Get your access token via a POST request to this url, using the code you got in the previous step.

https://intend.do/oauth/token?code=CODE&grant_type=authorization_code
&client_id=CLIENT_KEY&client_secret=CLIENT_SECRET
&redirect_uri=http://example.com/REDIRECT_URI/

You'll want to store this access token somewhere.

If this didn't work, then... google a bit about how to do OAuth2? It should be pretty standard. If you're still stuck, do get in touch.

Now, to access the endpoints below, use this header: Authorization: Bearer YOUR_ACCESS_CODE_GOES_HERE)

Data format:

See this javascript file for some documentation of the sorts of objects returned by the API.

API endpoints:

Great for testing—returns the user's name and username:

  • GET /api/v0/u/me/userinfo.json

Gets the user's list of goals, including each goal's current top priority:

  • GET /api/v0/u/me/goals/active.json

The item below returns most of the data used to render the user's today page

  • GET /api/v0/u/me/today/full.json
    which contains these sub-objects, that you can also access separately:
    • 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.json
    • settings ... GET /api/v0/u/me/today/settings.json
    • timer ... GET /api/v0/u/me/today/timer.json

Add new intention(s)

  • POST /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)
      • "count": how many items on the list, total (default)
      • "ntp": the next action (ntp stands for "new tab page"; this is the data used by the New Tab Page extension )
      • "today": the /today/full.json object
    }

Complete a specific intention

  • POST /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)

Post outcomes

  • POST /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)
    }

Retrieve past entries

  • GET /api/v0/u/me/timeline/entries.json
    Optional query parameters: (add as ?)
    • limit (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)
    Example: GET https://intend.do/api/v0/u/me/timeline/entries.json?startymd=2018-05-01&select=outcomes

Retrieve weekly reviews

To mimic the weekly reviews page, you may want to fetch the remarks for week n-1 and the overview for week n.

  • GET /api/v0/u/me/:year/week/:weeknum/remarks.json (the review remarks for a given week)
  • GET /api/v0/u/me/:year/week/:weeknum/overview.json (the outcomes for that week, by goal, with most of the goal info as well)

Timer

Creating new work blocks ('dur', short for duration)

  • POST /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: [...]}

  • POST /api/v0/u/me/addpomo
  • POST /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

{
  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

  • GET /api/v0/u/me/today/timer/all

Start pomodoro

  • POST /api/v0/u/me/today/timer/startpomodoro
    Query parameters: duration (in minutes; if omitted, uses current setting)

Start break

  • POST /api/v0/u/me/today/timer/startbreak
    Query parameters: duration (in minutes; if omitted, uses current setting)

Start hourglass timer

  • POST /api/v0/u/me/today/timer/hourglass
    Query parameters: duration (in minutes; if omitted, uses 15 minutes)

Pause timer

  • POST /api/v0/u/me/today/timer/pause

Unpause timer

  • POST /api/v0/u/me/today/timer/unpause

Cancel timer

  • POST /api/v0/u/me/today/timer/cancel

Custom timer update

  • POST /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)
    }
    Returns 400 if invalid in some way (eg pomo+paused or missing required field)

Beeminder

Get settings

  • GET /api/v0/u/me/apps/beeminder/settings.json

Put settings

  • PUT /api/v0/u/me/apps/beeminder/settings.json
    everything goes inside a property called "settings"
    {settings: {
    • intentionsBinary (beeminder goal slug for setting intentions at all)
    • outcomesBinary
    • outcomesPercentage
    • roomPresence
    • weeklyReviewCount
    • weeklyReviewComplete
    • monthlyReviewCount
    • monthlyReviewComplete
    • quarterlyReviewCount
    • quarterlyReviewComplete
    • arbitrary (array of "beemind arbitrary things" items)
    }}
    ...arbitrary object values: [{
    • 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)
    }]

Tell us what other endpoints you want

Use the question box on the right