Skip to content

API — goals router

backend/src/routers/goals.py (49 lines). APIRouter(prefix="/goals", tags=["goals"]) (goals.py:27). Exists to fill a gap: the habits PUT endpoint's HabitCreate carries no goal fields, so target/unit/frequency/is_additive could not be edited from the client (goals.py:1-8).

Method Path Auth Request DTO Response Success Errors
PUT /goals/{goal_id} JWT + owned goal GoalUpdate (backend/src/schemas/goal.py) Goal schema 200 404 goal_not_found (missing, orphaned, or not yours — collapsed for enumeration safety)

Ownership rides on the parent habit via the require_owned_goal dependency (backend/src/dependencies/ownership.py:118-130), which collapses "missing goal" and "not yours" into a single 404 (ownership.py:93-115). habit_id is deliberately absent from GoalUpdate "so the parent habit cannot be swapped via this endpoint — a goal is bound to its habit for life" (goals.py:37-42). The update applies every field of the payload, commits, and logs goal_updated (goals.py:43-49).

Model reference: data-model/habits-goals.


Grounded in adepthood@fbc529d, 2026-07-31.