---
title: "Email Test Send"
method: POST
path: "/v1/admin/email-test-send"
tags: ["admin"]
---

# Email Test Send

`POST /v1/admin/email-test-send`

## Request

- Base URL: `https://api.patricia.app` (the document declares no server; this is the origin it was published from)
- URL: `https://api.patricia.app/v1/admin/email-test-send`
- Auth: HTTP bearer

Render one catalog email with sample values and send it directly (admin verification only).

The audit row is written and COMMITTED BEFORE the provider call, not queued afterwards. This
route puts real mail into a real mailbox, at a caller-chosen address, from a caller-chosen
sender, so "we emailed someone and there is no record" must be unreachable. The post-commit
side-effect dispatcher cannot promise that: it runs after the transaction closes, writes in its
own session, and logs its failures instead of raising (``dependencies/audit.py``), so a queued
row can silently never land.

Ordering it before the send trades one honest failure mode for an unacceptable one. A row can
now exist for a send the provider then refused (over-recording, visible and harmless); a send
can never exist without a row (under-recording, the state the approval was about). It records
the REQUEST for that reason, and says so in its action name: ``platform_audit_logs`` is
append-only behind a ``prevent_mutation()`` trigger, so the row cannot be updated afterwards
with the delivery outcome. That outcome stays in the structured log below and in the response.

## Request body

- EmailTestSendRequest
  - `email_id` string, required
  - `to` string, email, required
  - `from_address` string, nullable

## Response `200`

Successful Response

- EmailTestSendResult
  - `email_id` string, required
  - `to` string, required
  - `subject` string, required
  - `provider_message_id` string, required

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden. Inspect response body `code` for the specific reason (for example: PERMISSION_DENIED, EMAIL_NOT_VERIFIED, TENANT_ACCESS_REQUIRED, ROLE_UNRESOLVED)
- `409`: Conflict
- `422`: Validation error

---

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