Concepts · Planning

Goals and pace

A goal is an outcome with a horizon. Give it a number and a date and it becomes a score: Esy reads the number from its source every hour, keeps one reading a day, and says whether the line is heading for the target in time, and what a week needs from here.

Horizons

HorizonEnds
dayToday
weekThis Sunday
monthThe month’s last day
quarterThe quarter’s last day
halfSix months on, less a day (Nov 1 → Apr 30)
yearDecember 31
visionNo end date

A measure

metric holds the number. A measured goal needs startsOn and endsOn: pace is progress against time.

FieldMeans
sourceWhere the number comes from (below).
unitWhat’s counted, in words: “subscribers”, “sales”.
startThe value on the start date. Left out, Esy fills it.
targetThe value to reach by the end date.
newsletterIdFor newsletter.subscribers: which newsletter. Left out, the organization’s main one.
SourceCountsStart when left out
newsletter.subscribersConfirmed readers on a newsletter’s list: the ones an issue reachesToday’s count
stripe.salesStripe charges since the start date, in the goal’s brand (or the whole organization). Refunds don’t count0
manualValues you check in, with a noteRequired

A source Esy can’t read refuses the goal when it’s created, rather than saving a goal that can never show a number.

a measured goaljsonc
POST /v1/goals
{
  "workspaceId": "…",
  "projectId": "…",                    // the brand; leave out for the organization
  "title": "1,000 newsletter subscribers",
  "horizon": "half",
  "startsOn": "2026-11-03",
  "endsOn": "2027-04-30",
  "metric": {
    "source": "newsletter.subscribers",
    "unit": "subscribers",
    "target": 1000                     // start: left out, Esy fills today's count
  }
}

Readings

Esy keeps one reading per goal per day: the day’s latest. A sweep reads every measured goal hourly; you can ask for a read now, or check in a value yourself for a manual goal. The chart on the goal reads the readings, oldest first.

Pace

Every goal with a measure comes back with pace, worked out by Esy from the measure and the dates.

pace on a goaljsonc
"pace": {
  "state": "behind",
  "expected": 240,        // where a straight line from start to target says you'd be today
  "projected": 667,       // where today's rate ends up by the end date
  "short": 333,
  "perWeekNeeded": 44,
  "perWeekNow": 26,
  "daysGone": 42,
  "daysLeft": 136
}
StateMeans
earlyUnder a week in: one good day says more than the trend.
on_paceThe projection reaches at least 95% of the target.
behindThe projection falls short.
reachedThe target is met.
endedPast the end date, short.

Milestones

A milestone is a smaller goal with parentGoalId set to the bigger one, with its own measure and end date. Dropping the big goal leaves its milestones.

Tasks under a goal

A task with a goalId is work toward that goal. That link is how the planner, and an agent, tell work that moves a goal from work that doesn’t.

Your goals, not a worker’s
metric is your own score. A worker’s goal uses target, a catalog count its shifts work toward (Assigned work). The two are separate fields.

Reference: Planning API. Where goals sit: The planner and The Plan.

In short
  • A measure is a source, a unit and a target, over a start and end date.
  • Esy reads it hourly and keeps one reading a day.
  • pace says where you are against the line, where you’ll land, and what a week needs.