{"openapi":"3.1.0","info":{"title":"Outstand Conversations v1","description":"# Conversations API\n\nRead and reply to inbound direct messages.\n\n## Key Concepts\n\n**Conversations** represent an ongoing thread between one of your connected accounts and a contact.\n\n**Messages** are individual messages within a conversation, in either direction.\n\n## 24-hour Messaging Window\n\nInstagram only allows free-form replies within 24 hours of the contact's last inbound message. Pass `instagram.tag` (`HUMAN_AGENT`) to widen the window to 7 days; without one, a send outside 24 hours is rejected with a 422.\n\n## Supported Networks\n\nInstagram Direct Messages.","version":"1.0.0"},"servers":[{"url":"https://api.outstand.so"}],"paths":{"/v1/conversations":{"get":{"operationId":"getV1Conversations","summary":"List conversations","description":"Get a paginated list of conversations for your organization. Optionally filter by social account, network, or status. Results are sorted by most recently active first.","tags":["Conversations"],"responses":{"200":{"description":"Conversations retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"9dyJS","description":"Conversation ID"},"orgId":{"type":"string"},"socialAccountId":{"type":"string","description":"Social account ID"},"network":{"type":"string","example":"instagram","description":"Messaging network"},"platformConversationId":{"type":"string"},"participantId":{"type":"string","description":"Contact's platform user ID (IGSID for Instagram)"},"participantDisplayName":{"type":["string","null"]},"participantProfilePicture":{"type":["string","null"]},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"lastInboundAt":{"type":["string","null"],"format":"date-time"},"unreadCount":{"type":"integer","description":"Inbound messages in this conversation that have not been marked read"},"status":{"type":"string","const":"active"},"metadata":{"type":["object","null"],"additionalProperties":{}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","orgId","socialAccountId","network","platformConversationId","participantId","unreadCount","status","createdAt","updatedAt"],"description":"A conversation with a participant"}},"pagination":{"type":"object","properties":{"hasMore":{"type":"boolean"},"nextCursor":{"type":["number","null"]},"limit":{"type":"number"}},"required":["hasMore","limit"]}},"required":["success","data","pagination"],"description":"List of conversations"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Conversation not found"}},"required":["success","error"],"description":"Error response"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Internal server error"}},"required":["success","error"],"description":"Internal server error response"}}}}},"parameters":[{"in":"query","name":"social_account_id","schema":{"type":"string"},"description":"Filter by Social account ID"},{"in":"query","name":"network","schema":{"type":"string","example":"instagram"},"description":"Filter by network"},{"in":"query","name":"status","schema":{"type":"string","const":"active"}},{"in":"query","name":"cursor","schema":{"type":"string"},"description":"Cursor for pagination (numeric ID of last item)"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}]}},"/v1/conversations/{id}":{"get":{"operationId":"getV1Conversations:id","summary":"Get conversation","description":"Get detailed information about a specific conversation, including participant details and unread count.","tags":["Conversations"],"responses":{"200":{"description":"Conversation retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"conversation":{"type":"object","properties":{"id":{"type":"string","example":"9dyJS","description":"Conversation ID"},"orgId":{"type":"string"},"socialAccountId":{"type":"string","description":"Social account ID"},"network":{"type":"string","example":"instagram","description":"Messaging network"},"platformConversationId":{"type":"string"},"participantId":{"type":"string","description":"Contact's platform user ID (IGSID for Instagram)"},"participantDisplayName":{"type":["string","null"]},"participantProfilePicture":{"type":["string","null"]},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"lastInboundAt":{"type":["string","null"],"format":"date-time"},"unreadCount":{"type":"integer","description":"Inbound messages in this conversation that have not been marked read"},"status":{"type":"string","const":"active"},"metadata":{"type":["object","null"],"additionalProperties":{}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","orgId","socialAccountId","network","platformConversationId","participantId","unreadCount","status","createdAt","updatedAt"],"description":"A conversation with a participant"}},"required":["success","conversation"],"description":"Single conversation details"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Conversation not found"}},"required":["success","error"],"description":"Error response"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Internal server error"}},"required":["success","error"],"description":"Internal server error response"}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}]}},"/v1/conversations/{id}/messages":{"get":{"operationId":"getV1Conversations:idMessages","summary":"List messages","description":"Get a paginated list of messages in a conversation. Results are ordered newest-first. Use `direction` to filter to inbound or outbound messages only.","tags":["Conversations"],"responses":{"200":{"description":"Messages retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"3kPqR","description":"Message ID"},"conversationId":{"type":"string"},"platformMessageId":{"type":["string","null"]},"direction":{"type":"string","enum":["inbound","outbound"]},"senderId":{"type":["string","null"]},"content":{"type":["string","null"]},"mediaUrls":{"type":["array","null"],"items":{"type":"string"}},"status":{"type":"string","enum":["pending","sent","read","failed","received"],"description":"Outbound messages run `pending` -> `sent` -> `read`, or `failed`. Inbound messages arrive `received` and become `read` when the conversation is marked read."},"error":{"type":["string","null"]},"scheduledAt":{"type":["string","null"],"format":"date-time","description":"When a scheduled message is due for delivery. Null for messages sent on submit."},"platformSentAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","conversationId","direction","status","createdAt"],"description":"A message within a conversation"}},"pagination":{"type":"object","properties":{"hasMore":{"type":"boolean"},"nextCursor":{"type":["number","null"]},"limit":{"type":"number"}},"required":["hasMore","limit"]}},"required":["success","data","pagination"],"description":"List of messages in a conversation"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Conversation not found"}},"required":["success","error"],"description":"Error response"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Internal server error"}},"required":["success","error"],"description":"Internal server error response"}}}}},"parameters":[{"in":"query","name":"direction","schema":{"type":"string","enum":["inbound","outbound"]}},{"in":"query","name":"cursor","schema":{"type":"string"}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"schema":{"type":"string"},"in":"path","name":"id","required":true}]},"post":{"operationId":"postV1Conversations:idMessages","summary":"Send a message","description":"Send text, one or more media attachments, or both to a conversation participant. At least one of `content` or `media_urls` is required.\n\n**Async delivery**: the request returns `202 Accepted` immediately with a `pending` message. Final outcome arrives via the `message.sent` / `message.failed` webhook, or by polling `GET /v1/conversations/:id/messages`.\n\n**Scheduling**: pass `scheduled_at` to deliver the message at a future time instead of immediately. The message is returned as `pending` with `scheduled_at` set, and the delivery webhook fires when it goes out.\n\nFree-form text messages are only allowed within 24 hours of the contact's last inbound message. Pass `instagram.tag` as `HUMAN_AGENT` to reply for up to 7 days after the contact's last message. The window check is always synchronous, so you receive a 422 immediately - for a scheduled message it is applied to `scheduled_at`, so a send that would land outside the window is rejected up front.","tags":["Conversations"],"responses":{"202":{"description":"Message accepted — delivery is in progress asynchronously","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"object","properties":{"id":{"type":"string","example":"3kPqR","description":"Message ID"},"conversationId":{"type":"string"},"platformMessageId":{"type":["string","null"]},"direction":{"type":"string","enum":["inbound","outbound"]},"senderId":{"type":["string","null"]},"content":{"type":["string","null"]},"mediaUrls":{"type":["array","null"],"items":{"type":"string"}},"status":{"type":"string","enum":["pending","sent","read","failed","received"],"description":"Outbound messages run `pending` -> `sent` -> `read`, or `failed`. Inbound messages arrive `received` and become `read` when the conversation is marked read."},"error":{"type":["string","null"]},"scheduledAt":{"type":["string","null"],"format":"date-time","description":"When a scheduled message is due for delivery. Null for messages sent on submit."},"platformSentAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","conversationId","direction","status","createdAt"],"description":"A message within a conversation"}},"required":["success","message"],"description":"Message sent successfully"}}}},"400":{"description":"Invalid request body, or `scheduled_at` is not a valid future timestamp","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Conversation not found"}},"required":["success","error"],"description":"Error response"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Conversation not found"}},"required":["success","error"],"description":"Error response"}}}},"422":{"description":"The messaging window has expired; supply `instagram.tag` to reply for up to 7 days","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Conversation not found"}},"required":["success","error"],"description":"Error response"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Internal server error"}},"required":["success","error"],"description":"Internal server error response"}}}}},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","minLength":1,"description":"Text body of the message. Either non-blank content or at least one media URL is required.","example":"Hello! How can I help you today?"},"instagram":{"type":"object","properties":{"tag":{"type":"string","enum":["HUMAN_AGENT"],"description":"Send outside the 24h messaging window by tagging the reason. `HUMAN_AGENT` (a human replying to a support issue) widens the window to 7 days and requires App Review plus business verification on the Meta app that owns the conversation.","example":"HUMAN_AGENT"}},"description":"Instagram-specific message options.","example":{"tag":"HUMAN_AGENT"}},"media_urls":{"type":"array","items":{"type":"string","format":"uri"},"description":"Media to attach to the message. Either non-blank content or at least one media URL is required."},"scheduled_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp to deliver the message at, instead of on submit. Must be in the future. The messaging window is checked against this time, so scheduling past the end of the contact's window is rejected with 422.","example":"2026-09-01T09:00:00.000Z"}},"description":"Send a text message, one or more media attachments, or both to a conversation participant"}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}]}},"/v1/conversations/{id}/messages/{messageId}":{"delete":{"operationId":"deleteV1Conversations:idMessages:messageId","summary":"Cancel a scheduled message","description":"Cancel a message that was scheduled with `scheduled_at` but has not been delivered yet. The message is removed from the sending queue and deleted. This action cannot be undone.\n\nOnly a scheduled message still in `pending` can be cancelled: a message already sent, delivered or failed returns 409, as does one that was never scheduled (it is delivered on submit, so there is nothing to call back).","tags":["Conversations"],"responses":{"200":{"description":"Scheduled message cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string","example":"Message cancelled successfully"}},"required":["success","message"],"description":"Scheduled message cancelled and deleted"}}}},"404":{"description":"Message not found in this conversation","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Conversation not found"}},"required":["success","error"],"description":"Error response"}}}},"409":{"description":"The message is not a scheduled message, or is no longer pending","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Conversation not found"}},"required":["success","error"],"description":"Error response"}}}},"500":{"description":"Internal server error, including a failure to remove the message from the sending queue","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Internal server error"}},"required":["success","error"],"description":"Internal server error response"}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"path","name":"messageId","required":true}]}},"/v1/conversations/{id}/read":{"post":{"operationId":"postV1Conversations:idRead","summary":"Mark conversation as read","description":"Mark all messages in a conversation as read. This sends a read receipt to the contact on the underlying network and resets the unread count to 0.","tags":["Conversations"],"responses":{"200":{"description":"Conversation marked as read","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"id":{"type":"string"},"unreadCount":{"type":"integer"}},"required":["success","id","unreadCount"],"description":"Conversation marked as read"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Conversation not found"}},"required":["success","error"],"description":"Error response"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","example":"Internal server error"}},"required":["success","error"],"description":"Internal server error response"}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}]}}},"components":{}}