---
title: "Publish Goal"
method: POST
path: "/goals/{goal_id}/publish"
tags: ["goals"]
---

# Publish Goal

`POST /goals/{goal_id}/publish`

Publish this browser's goal, and hand back the page it produced.

Only a settled goal has a promise to show, so an unsettled one is refused
rather than published as a blank. Publishing twice is idempotent on an
unchanged promise; publishing a changed one keeps the live link and dates
the change.

## Path parameters

- `goal_id` string, required

## Response `200`

Successful Response

- GoalSharePage — The published goal, as a stranger sees it. **The promise, at a distance — and its picture.** The goal's name, when it is, how precisely that date is known, what kind of goal it is, the sport, the dated history of it changing, and the goal's picture: wonderland goals.md makes the picture the page's highlight and what the link preview carries, both sides published, what the goal asks and where the athlete stands, gap and all. ``factors`` is the owner-side shape exactly (:class:`~cheshire.goals.models.GoalFactor`): positions on the goal's own scale, never the readings behind them — a body-read factor publishes as a position, and the sleep or recovery data underneath it never leaves. What is absent is still the point. The document body, the checkpoints and fallbacks, the athlete's reasons — the why and what chose the event stay theirs to tell (wonderland #45) — and every session id, none of it is here. Sharing a goal must feel safe; it must never feel like exposing something internal. Three layers keep it that way: this model is `extra="forbid"` so an added field cannot ride along silently, the validator below walks the serialized payload for forbidden keys and internal markers, and the row is projected field by named field rather than dumped. **The field list is settled** by wonderland goals.md's share-page section (the human review the earlier note here waited on). Trimming a field is cheap; un-leaking one is not.
  - `share_id` string, required
  - `slug` string, required
  - `name` string, required
  - `kind` 'destination' | 'practice', required
  - `target_date` string, date, required
  - `target_precision` 'day' | 'month' | 'quarter' | 'season', required
  - `sport` string, nullable
  - `locale` string, required
  - `factors` object[]
  - `revisions` GoalShareRevision[]
    - `published_at` string, date-time, required
    - `name` string, required
    - `target_date` string, date, required
    - `target_precision` 'day' | 'month' | 'quarter' | 'season', required

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/imperfect/apis/imperfect-api.md) · [All operations](https://skmtc.dev/imperfect/apis/imperfect-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/imperfect/imperfect-api/revisions/effd5836988d/schema)
