---
title: "EPIC-KEYS-001A T2 — operator-authorized one-shot custody-notice delivery"
method: POST
path: "/api/v1/admin/provider-custody-notice/authorize-delivery"
tags: ["admin"]
---

# EPIC-KEYS-001A T2 — operator-authorized one-shot custody-notice delivery

`POST /api/v1/admin/provider-custody-notice/authorize-delivery`

## Request

- Base URL: `https://api.badgeia.com`
- URL: `https://api.badgeia.com/api/v1/admin/provider-custody-notice/authorize-delivery`
- Auth: none declared

Send the reviewed custody notice to the pending cohort, once each.

This is the operator action itself. Flipping
``PROVIDER_CUSTODY_NOTICE_ENABLED`` makes the endpoint exist; calling it with
a body that transcribes the previewed cohort size and copy hash is what
authorizes the send. Neither alone sends anything.

The copy is ``services/provider_custody_notice.render_...()`` UNCHANGED —
this handler never templates, personalizes, or interpolates anything into it,
which is what keeps the reviewed identity-free copy module identity-free.

Responses:
    200 — counts-only delivery result (see the service dataclass).
    400 — the gate flipped off between the request and the service call.
    409 — the confirmed recipient count or notice version no longer matches
          the live cohort. A stale preview never sends.
    422 — ``confirm_delivery`` was not explicitly true.
    503 — flag on, no Resend key (Sentry-allowlisted; see observability).

Authorization / flag gates identical to the preview endpoint.

Durability note: the per-recipient record of what was sent is the
``provider_custody_notice_deliveries`` ledger, committed per recipient as
delivery proceeds. The audit row below is the operator-attribution record for
the batch and is written after the batch completes, so a process death
mid-batch leaves the ledger authoritative and the batch un-audited — the next
preview shows the ledger state, and re-authorizing is safe because
already-sent recipients are skipped.

## Request body

- AdminProviderCustodyNoticeAuthorization: Body for POST /admin/provider-custody-notice/authorize-delivery. EPIC-KEYS-001A T2. This is the only request in the codebase whose success sends unsolicited mail to customers, so the body is an attestation, not a trigger — every field must be transcribed from a preview the operator just read, and there is no default that makes an empty POST meaningful. ``expected_recipient_count`` and ``expected_notice_version`` are checked against a freshly derived cohort in the handler and 409 on drift (see ``services/provider_custody_notice_cohort.deliver_custody_notice``). That is what stops a stale preview from authorizing a batch the operator never saw: a cohort that grew since the preview, or copy that changed under them, is refused rather than silently sent. Nothing here is or can become a recipient identity — an integer, a content hash, and a boolean.
  - `expected_recipient_count` integer, required
  - `expected_notice_version` string, required
  - `confirm_delivery` boolean

## Response `200`

Successful Response

- object

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/badgeia/apis/badge.md) · [All operations](https://skmtc.dev/badgeia/apis/badge/llms.txt) · [OpenAPI document](https://skmtc.dev/badgeia/apis/badge/revisions/7e7f7fee8b77?raw)
