---
title: "Send a direct message"
method: POST
path: "/v1/inbox/conversations/{conversationId}/messages"
tags: ["Inbox"]
---

# Send a direct message

`POST /v1/inbox/conversations/{conversationId}/messages`

## Request

- Base URL: `https://api.postzen.dev`
- URL: `https://api.postzen.dev/v1/inbox/conversations/{conversationId}/messages`
- Auth: HTTP bearer

Sends a message into an existing thread. The recipient is the other participant on that thread, so no recipient id is needed. Exactly one of `message` or `attachmentUrl` may be sent per call — Meta's Send API carries one payload at a time, so combining them is a 400. Meta only accepts replies within 24 hours of the person's last message; outside that window the platform refuses the send and PostZen reports `400 PLATFORM_LIMITATION` with Meta's own envelope attached. Sends are hard-gated on the account's messaging scope. Requires a read-write API key.

## Headers

- `Idempotency-Key` string

## Request body

- InboxMessageSendRequest: Exactly one of `message` or `attachmentUrl` is required. Meta’s Send API carries one payload per call, so the two cannot be combined — send two messages instead.
  - `accountId` string, required: PostZen account id that owns the conversation.
  - `message` string: Message text. Cannot be combined with `attachmentUrl`: Meta accepts one payload per call, so a request carrying both is rejected with a 400 rather than silently sending half of it.
  - `attachmentUrl` string, uri: Publicly fetchable http(s) URL. Meta downloads it itself, so it must be reachable without credentials — `POST /v1/media/upload-direct` returns a URL that qualifies.
  - `attachmentType` 'image' | 'video' | 'audio' | 'file': Required whenever `attachmentUrl` is set.

## Response `200`

Message sent. `Idempotent-Replayed: true` on the response means this was a replay of an earlier identical request rather than a new send.

- InboxMessageSendResponse
  - `success` true, required
  - `data` object, required
    - `messageId` string, required
    - `conversationId` string, required
    - `sentAt` string, date-time, required
    - `message` string

## Other responses

- `400`: A parameter is missing or malformed, `message` and `attachmentUrl` were combined, the account is not on a supported platform (`platformUnsupported`), or the platform refused a send it could accept at another time (`PLATFORM_LIMITATION`).
- `401`: Missing or invalid API key.
- `403`: The account is outside the API key's profile access (`forbidden`), or the connection is missing the messaging scope this call needs (`platformCapabilityMissing`). Reconnect the account to grant it.
- `404`: No such account (`accountNotFound`) or no such conversation for that account (`conversationNotFound`).
- `409`: A request with the same `Idempotency-Key` is still in flight (`idempotencyInFlight`). Retry once it settles.
- `422`: That `Idempotency-Key` was already used with a different request body (`idempotencyConflict`).
- `424`: The connection needs to be reauthorized before its messages can be read (`connectionDead`).
- `429`: Rate limit exceeded. Retry after the interval indicated by the `Retry-After` header.
- `500`: Unexpected server error.
- `502`: The send request to Meta did not come back (timeout or transport fault), so PostZen cannot confirm whether the message was delivered (`providerOutcomeUnknown`). Check the conversation before sending again — retrying the same `Idempotency-Key` returns this same response rather than sending a second copy.

---

[API](https://skmtc.dev/postzen/apis/postzen-public-api.md) · [All operations](https://skmtc.dev/postzen/apis/postzen-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/postzen/apis/postzen-public-api/revisions/40863e3710ec?raw)
