Create Success Plan Goal
POST/api/success-plan/goals
Creates a goal with its baseline. The title is the customer's own words; the template only pre-fills the unit, direction and measurement. A plan holds at most three active goals.
success_plan:writeGrant this scope to your token under Settings → Developer → Personal Access Tokens.
Authentication: Requires Bearer token with the success_plan:write scope. The user must hold the success_plan.manage permission.
Body:
template_key(string, required):ops_hours,oversells,year_end_adjustment,close_days,margin_visibility,growth_without_hires,spreadsheets_retired,peak_handledorcustom. See Get Goal Templates.title(string, required, 5–200).unit(string, required): one of the template's units:hours_per_week,count_per_month,units,currency,days,boolean,percent_of_units,percent_of_value. A bare "percent" is refused: name what it is a percentage of.direction(string, optional):lower_is_better,higher_is_betterorreach_yes; onlycustomgoals choose, other templates use their own.options.count_kind(string):oversells,backordersorboth; required foroversells.options.adjustment_basis(string):netorgross; required foryear_end_adjustment.options.peak_window.start,options.peak_window.end(string,MM-DD): the peak window forpeak_handled.options.spreadsheets(string array, max 30, each 1–120): the spreadsheets kept today, forspreadsheets_retired.target.value(number, optional): leave it out for a goal you mark met yourself.target.by_date(dateY-m-d, optional, in the future): defaults to 180 days after go-live.baseline(object): required in kickoff mode; optional in retrospective mode, where the before can be answered later through Correct Goal Baseline.
Baseline Fields:
value(number): the figure. Required unlessuse_measured/use_importedis true, or the unit ishours_per_week(sendroles) orboolean(sendvalue_bool). 0–100 for percentage units; zero or more for counts, units and days.value_bool(boolean): yes / no forbooleangoals.roles(array, 1–20): hours by role forhours_per_weekgoals; each row isrole(string, required, max 60) andhours_per_week(number 0–168, required). The value is the total. Not allowed on other units.as_of(date,Y-m-d): when the figure was true. Required with a typed value; never in the future; at most 365 days back (in retrospective mode, back to the start of the month before go-live).evidence(string): how you know it:document,system_exportorestimate(recallis also accepted in retrospective mode). Required with a typed value. Ignored withuse_measured/use_imported: SKU.io records its own figure assystem.source_note(string, max 255): where the figure came from.range_low,range_high(number): only withestimateorrecall; required withrecall. The value must sit inside the range.confidence(string):high,mediumorlow; only withestimateorrecall; required withrecall.attachment_ids(integer array, max 10): uploaded evidence files; only withdocumentorsystem_exportevidence.use_measured(boolean): use SKU.io's measured figure for last month instead of a typed value (measured templates only).use_imported(boolean): retrospective mode only; use orders imported from before go-live.
For a measured template, "baseline": {"use_measured": true} uses SKU.io's figure for last month.
Returns the goal (201) plus warnings: total_hours_zero when an hours-by-role baseline totals 0 hours a week.
Refused writes answer 422 with a machine-readable code alongside the usual errors, where each error is {message, code}: max_active_goals (three active goals at most; archive one first), measured_baseline_unavailable, imported_baseline_unavailable, baseline_required, unit_not_allowed, goal_archived, goal_has_target.
Goal objects carry id, template_key, template_name, metric_key (null for goals only the customer measures), title (the customer's own words), unit, direction, status (no_data, on_track, off_track, met, archived) with status_label, options, baseline, latest (the newest reading other than the current month) and current (this month's provisional measured figure), change (absolute, percent, mixed_sources, compared_with, baseline_compared_value), target (value, by_date), expected_now (a straight line from baseline to target), first_measurement_after, before_answered, before_period, first_30_days, trend (measured months, oldest first), next_steps (key, title, why, route, cta, done), hero_eligible and hero_ineligible_reasons (e.g. baseline_estimate, latest_not_settled, latest_missing), met_at, archived_at and created_at.
Request
Responses
- 201
- 401
- 403
- 404
- 422
- 429
Created
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden — the token lacks a required scope, the endpoint is not available to API tokens, or the user behind the token lacks the permission. A human must adjust the token scopes or user permissions; do not retry.
Not Found
Response Headers
Unprocessable Entity
Response Headers
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.