---
title: "Set Speaker Onboarding Checklist"
method: PUT
path: "/speakers/{speaker_id}/onboarding-checklist"
tags: ["speakers"]
---

# Set Speaker Onboarding Checklist

`PUT /speakers/{speaker_id}/onboarding-checklist`

## Request

- Base URL: `https://api.verdun.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.verdun.ai/speakers/{speaker_id}/onboarding-checklist`
- Auth: HTTP bearer

Merge the owner's device-setup attestations. PARTIAL — send only what
changed.

ITS OWN ROUTE, NEVER `PUT /speakers/{id}`: that body is a full replace that
re-defaults every omitted field, so checklist state living there would be
one forgotten key away from an unrelated edit wiping the record of a device
someone drove to a site to configure.

## Path parameters

- `speaker_id` string, required

## Request body

- SetSpeakerChecklistRequest: PARTIAL BY DESIGN: send only the items that changed. Merge semantics, not full replacement, and that is the whole reason this is its own route rather than three more fields on `PUT /speakers/{id}`. That body is a full replace that re-defaults every omitted field, so checklist state living there would be one forgotten key away from an unrelated edit wiping the record of a device someone drove to a site to configure. `true` confirms an item, `false` un-confirms it. `done_at` and the confirming operator are stamped SERVER-SIDE — a client cannot backdate an attestation about a safety-relevant device configuration. THE KEYS ARE A BACKEND ENUM, so an unknown one is a 422 rather than a silent write under a key nothing reads. `default_account` is refused too: it is derived from the device's own `GetSIPAccounts` answer, and a hand-typed tick for it would be strictly worse evidence than the one the device gives.
  - `items` object, required: The checklist items to set, keyed by item id. Omitted items are left exactly as they are.

## Response `200`

Successful Response

- SpeakerChecklistResponse: A speaker's device-setup checklist after a merge write. The envelope is `{"version", "items"}`. `items` holds the owner's own attestations, each stamped server-side with `done_at` and a snapshot of who confirmed it; an absent key means "not confirmed". THE DEVICE'S OWN TICK IS NOT IN HERE, deliberately: it is computed from the live `GET /speakers/{id}/sip-accounts` read and returned there, so there is no stored copy to go stale or to be forged. `confirmed_count` and `total_count` are therefore over the ATTESTABLE items only — a fully set-up speaker reads N of N rather than N-1 of N.
  - `speaker_id` string, uuid, required: The speaker this checklist belongs to.
  - `speaker_label` string, required: The speaker's display name.
  - `onboarding_checklist` object, required: The whole stored envelope: `{"version": 1, "items": {...}}`.
  - `confirmed_count` integer, required: How many of the attestable items the owner has confirmed.
  - `total_count` integer, required: How many attestable items there are. Excludes the items the device answers for itself.

## Other responses

- `422`: Validation Error

---

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