---
title: "Draft owed milestone summaries across every project (every 10 minutes)"
method: POST
path: "/cron/milestone-summaries"
tags: ["Cron"]
---

# Draft owed milestone summaries across every project (every 10 minutes)

`POST /cron/milestone-summaries`

## Request

- Base URL: `https://api.apphandoff.com/api`
- URL: `https://api.apphandoff.com/api/cron/milestone-summaries`
- Auth: none required

HO-15533. Picks milestones whose summary_stale_at is older than 60 s, not done or dropped, not merged, not a failure younger than 30 minutes and not under a live draft lease, oldest stamp first, at most 5 per project and 40 per run, and runs the same summary refresh as the on-read scheduler, 3 at a time. Each refresh takes the row's draft lease (summary_draft_claimed_at, 2 minutes) before any model call, so another machine, an overlapping run or a board read never pays twice for one draft. No refresh starts after 30 s; the run stops after 5 consecutive model failures. ok is false only when the pick read fails. Protected by CRON_SECRET via the x-cron-secret header. Scheduled by the milestone-summaries stage of the embedding-drain schedule in .slipstream.json.

## Response `200`

Run result

- object
  - `ok` boolean, required
  - `picked` integer, required
  - `written` integer, required
  - `cleared` integer, required
  - `unchanged` integer, required
  - `rejected` integer, required
  - `failed` integer, required
  - `skipped` integer, required
  - `leased_elsewhere` integer, required
  - `stopped` 'drained' | 'budget' | 'model_failures', required
  - `window_full` boolean, required
  - `duration_ms` integer, required
  - `error` string

## Other responses

- `401`: Missing or invalid CRON_SECRET

---

[API](https://skmtc.dev/apphandoff/apis/apphandoff-api.md) · [All operations](https://skmtc.dev/apphandoff/apis/apphandoff-api/llms.txt) · [OpenAPI document](https://skmtc.dev/apphandoff/apis/apphandoff-api/revisions/9f138fe46d56?raw)
