Send a direct message
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.
Authorization
bearerAuth PostZen API key.
In: header
Path Parameters
The platform's own conversation (thread) id, as returned in id by the list and search endpoints — not a PostZen document id.
Header Parameters
Replay protection. Retrying with the same key and the same body replays the stored outcome and sets Idempotent-Replayed: true; the same key with a different body is a 422, and a key whose first request is still in flight is a 409. A send whose outcome could not be confirmed (502 providerOutcomeUnknown) is stored as a terminal outcome, so retrying that key returns the same 502 rather than risking a duplicate message. Keys are retained for 24 hours.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
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.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/inbox/conversations/string/messages" \ -H "Content-Type: application/json" \ -d '{ "accountId": "k17d8s9f0a1b2c3d4e5f6g7h8i", "message": "Yes — the sale runs through Friday!" }'{ "success": true, "data": { "messageId": "aWdfZGFtOm1zZ18y", "conversationId": "t_17845791234567890", "sentAt": "2026-08-18T16:14:52.000Z", "message": "Yes — the sale runs through Friday!" }}{ "error": "This message is sent outside of allowed window.", "code": "PLATFORM_LIMITATION", "platform": "instagram", "platformError": { "code": 10, "subcode": 2534022, "type": "OAuthException" }}{ "error": "Unauthorized"}{ "error": "Reconnect the account to grant PostZen access to its messages.", "code": "platformCapabilityMissing", "platform": "instagram"}{ "error": "That conversation could not be found.", "code": "conversationNotFound"}{ "error": "A request with that Idempotency-Key is still in flight.", "code": "idempotencyInFlight"}{ "error": "That Idempotency-Key was already used with a different request body.", "code": "idempotencyConflict"}{ "error": "This connection needs to be reauthorized before its messages can be read.", "code": "connectionDead"}{ "error": "rate_limited", "retryAfter": 30}{ "error": "Failed to create post"}{ "error": "Message delivery outcome unknown — do not retry with the same idempotency key. Check the conversation before sending again.", "code": "providerOutcomeUnknown", "platform": "instagram"}List messages in a conversation GET
Returns the messages PostZen holds for one thread, oldest first by default, refreshing them from the platform when the stored copy is stale. Strictly read-only: it never marks the thread read — use `POST /v1/inbox/conversations/{conversationId}/read` for that. Meta returns full content only for roughly the twenty newest Instagram messages, so older ones may carry an id and timestamp without text or attachments. Read-only and read-write API keys are accepted.
Get a queue schedule GET
Returns the queue selected by `queueId`, or the profile's default queue when `queueId` is omitted. With `all=true` every queue on the profile is returned instead. `nextSlots` holds the next five instants the queue would hand out, already skipping occupied slots; a paused or slotless queue returns an empty array.