---
title: "Create Answer Page From Message"
method: POST
path: "/api/domains/{domain_id}/agent-desk/answer-pages/from-message"
tags: ["agent_desk"]
---

# Create Answer Page From Message

`POST /api/domains/{domain_id}/agent-desk/answer-pages/from-message`

## Request

- Base URL: `https://api-v1.unusual.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api-v1.unusual.ai/api/domains/{domain_id}/agent-desk/answer-pages/from-message`
- Auth: OAuth 2
  - Password
  - Token URL: `/auth/login`

Publish a permanent page from ONE answer your AgentDesk already gave.

AGENTDESK-RD(c1), Will's directive 2026-08-07: "in all the answers we need the
ability to create a permanent page for the question". `POST
/answer-pages/{id}/pin` publishes an answer page that ALREADY EXISTS, and answer
pages only come into existence when an agent fetches a question-shaped URL — so
a conversation turn (and every Sandbox turn) had no route to a page. This is
that route, and it ends in the SAME `_pin_answer_page_row` the pin uses, which
is what keeps the published-pages billing sync on one path.

── THE THREE OUTCOMES FOR A QUESTION THAT ALREADY HAS A PAGE ───────────────

An answer page is addressed by `(domain, slug)` and the slug is derived from the
question, so "does this answer already have a page" is a question about the
slug, and the three answers are genuinely different:

  * a **pinned** page at that slug → **409**. The question already has a
    published page; publishing a second one at an adjusted slug would split the
    same question across two URLs and bill for both.
  * an **ephemeral** page at that slug → that row is PINNED. It is the row the
    desk already serves this question at, so publishing it is what the owner
    asked for; minting a second row would leave the served URL unpublished.
    (Its stored answer stays as-is — the stored answer IS what the URL serves,
    and overwriting it here would publish text no agent has ever been given.)
  * **nothing** at that slug → a new row, at a slug from
    `_allocate_answer_page_slug` (a `rejected` row can be squatting it).

The new row's `llm_*` columns are copied from the ASSISTANT MESSAGE, because
that is what generating this answer actually cost — the same aggregate the
answer-page lane stamps at generation, so cost-per-page stays a real number
rather than a NULL that averages in as free. `fetch_count` is 0: no agent has
fetched this URL, and starting it at the generated-page default of 1 would
claim a fetch that never happened (and, at 2, would make the Desk feed call it
repeat demand).

## Path parameters

- `domain_id` string, required

## Headers

- `x-view-as` string, nullable

## Request body

- AnswerPageFromMessageIn: AGENTDESK-RD(c1): publish a page from ONE conversation answer. Will's directive, 2026-08-07: "in all the answers we need the ability to create a permanent page for the question". Until now `POST /answer-pages/{id}/pin` could only publish a page that ALREADY EXISTED — answer pages are minted by an agent fetching a question-shaped URL — so a conversation turn and every Sandbox turn had no route to a page at all, and the Desk feed's conversation rows carried a comment saying exactly that.
  - `message_id` string, required

## Response `200`

Successful Response

- AnswerPagePinOut
  - `id` string, required
  - `status` string, required
  - `content_document_id` string, required
  - `document_slug` string, required
  - `message` string, required
  - `answer_page_slug` string

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/unusual/apis/dashboard-server.md) - [All operations](https://skmtc.dev/unusual/apis/dashboard-server/llms.txt) - [OpenAPI document](https://skmtc.dev/unusual/apis/dashboard-server/revisions/89f716930ead?raw)
