> ## Documentation Index
> Fetch the complete documentation index at: https://opentrain.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Start Proposal Conversation

> Open (or reuse) the pre-hire direct-message thread with a candidate. Employer-first; idempotent.

Opens the pre-hire direct-message thread for one of your proposals so you can talk to the candidate before hiring. Idempotent: if the thread already exists, you get the same `conversationId` back with `created: false`. Once you have the ID, send with [`POST /messages`](/docs/developers/api-reference/messages/send) and read with [`GET /messages`](/docs/developers/api-reference/messages/list).

Proposal conversations are **employer-first**: only the job owner can open the thread, and the candidate cannot reply until the employer has sent the first message. This endpoint never creates any other kind of conversation — job threads come from [hiring](/docs/developers/api-reference/proposals/hire).

**Requirements:** `messages:write` scope + the `public_api_messaging_writes` feature + a **claimed** account (unclaimed accounts get `403` with `details.reason: "account_claim_required"` and a `claimUrl`). The proposal must be on a job you own.

## Request

<ParamField path="proposalId" type="string" required>
  The proposal whose thread to open.
</ParamField>

No body.

## Response

<ResponseField name="ok" type="boolean">
  `true` on success.
</ResponseField>

<ResponseField name="conversationId" type="string">
  The conversation to use with the [messages endpoints](/docs/developers/api-reference/messages/send).
</ResponseField>

<ResponseField name="proposalId" type="string">
  The proposal ID.
</ResponseField>

<ResponseField name="jobId" type="string">
  The job the proposal belongs to.
</ResponseField>

<ResponseField name="created" type="boolean">
  `true` when a new thread was created, `false` when an existing one was returned.
</ResponseField>

## Errors

| Status | `code`         | Meaning                                                                                                                                                                                                                                                                                               |
| ------ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `BAD_REQUEST`  | Missing `proposalId`                                                                                                                                                                                                                                                                                  |
| `401`  | `UNAUTHORIZED` | Missing or invalid token                                                                                                                                                                                                                                                                              |
| `403`  | `FORBIDDEN`    | Missing `messages:write` scope, feature disabled, account not claimed (`details.reason: "account_claim_required"`, `details.claimUrl`), the proposal is on another account's job, or you are the candidate (`details.reason: "employer_first_message_required"` — only the employer opens the thread) |
| `404`  | `NOT_FOUND`    | No such proposal                                                                                                                                                                                                                                                                                      |
| `409`  | `CONFLICT`     | Proposal is not ready for messaging — `details.reason: "proposal_not_ready_for_messaging"` (e.g. missing invited user or linked job)                                                                                                                                                                  |

<RequestExample>
  ```bash curl theme={null}
  curl -sS -X POST https://app.opentrain.ai/api/public/v1/proposals/<PROPOSAL_ID>/conversation \
    -H "Authorization: Bearer $OT_API_TOKEN"
  ```

  ```bash CLI theme={null}
  opentrain messages start-proposal-thread --proposal-id <PROPOSAL_ID> --json
  ```

  ```json MCP: opentrain_start_proposal_conversation theme={null}
  {
    "proposalId": "<PROPOSAL_ID>"
  }
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "ok": true,
    "conversationId": "<CONVERSATION_ID>",
    "proposalId": "<PROPOSAL_ID>",
    "jobId": "<JOB_ID>",
    "created": true
  }
  ```
</ResponseExample>
