---
title: "Create a message in a thread (with optional attachments)"
method: POST
path: "/companies/{companyId}/threads/{threadId}/messages"
tags: ["Threads"]
---

# Create a message in a thread (with optional attachments)

`POST /companies/{companyId}/threads/{threadId}/messages`

## Request

- Base URL: `https://api.medianfi.com/api/v1`
- URL: `https://api.medianfi.com/api/v1/companies/{companyId}/threads/{threadId}/messages`
- Auth: HTTP bearer

Every attached document or transaction is admitted against the thread's company and the caller's authority before anything is written; the message and its attachments are stored together or not at all.

## Request body

- CreateThreadMessageInput: Either a non-empty body or at least one attachment is required; an attachment-only message may omit the body or send it empty.
  - `body` string
  - `attachments` ThreadAttachmentInput[]
    - `type` 'file' | 'link' | 'document' | 'transaction'
    - `label` string
    - `url` string, nullable: An http(s) URL or a root-relative path. Required for `link`; ignored for `document` and `file`.
    - `refId` string, uuid: Required for `document`, `file` and `transaction`.

## Response `201`

Message created

- ThreadMessageResponse
  - `success` boolean
  - `data` ThreadMessage
    - `id` string, uuid
    - `threadId` string, uuid
    - `companyId` string, uuid
    - `authorId` string, uuid, nullable
    - `body` string
    - `attachments` ThreadAttachment[]
      - `id` string, uuid, required
      - `messageId` string, uuid, required
      - `type` 'file' | 'link' | 'document' | 'transaction' | 'schedule_proposal', required
      - `label` string, nullable, required
      - `url` string, nullable, required: The stored link of a `link` or `transaction` attachment: an http(s) URL or a root-relative path. Always null for a `document` or `file` attachment, whose link is `downloadUrl`.
      - `refId` string, uuid, nullable, required: The referenced document or transaction. It is resolved only inside the thread's own company.
      - `available` boolean, required: False when a `document` or `file` attachment does not resolve for this caller: the reference is missing, belongs elsewhere, is outside the caller's authority, or its stored file is not servable. The reason is not disclosed. Always true for other kinds.
      - `downloadUrl` string, nullable, required: A download link minted for this caller on this read, valid until `downloadUrlExpiresAt`. Root-relative. Null unless the attachment is an available `document` or `file`. The download endpoint checks the caller's access again when the link is used.
      - `downloadUrlExpiresAt` string, date-time, nullable, required
      - `createdAt` string, date-time, required
    - `createdAt` string, date-time
    - `updatedAt` string, date-time

## Other responses

- `401`: Authentication required
- `403`: Insufficient permissions or not a company member
- `404`: The thread was not found, or an attached document or transaction does not resolve for the caller in this company. A reference that belongs to another company, one that does not exist and one the caller has no authority over get the same answer. Nothing is written.
- `422`: Validation error, or `THREAD_ATTACHMENT_NOT_ACCEPTED`: an attached document the caller may see has no stored file or its scan verdict is not clean. Nothing is written.

---

[API](https://skmtc.dev/medianfi/apis/median-api.md) · [All operations](https://skmtc.dev/medianfi/apis/median-api/llms.txt) · [OpenAPI document](https://skmtc.dev/medianfi/apis/median-api/revisions/20090ea32b0d?raw)
