# retoor <retoor@molodetz.nl>
from .._shared import endpoint, field
GROUP = {
"slug": "messaging",
"title": "Messaging",
"intro": """
# Messaging
Direct messages between users. The inbox renders HTML; sending uses form fields. Look up
recipients with [Search & Lookups](/docs/lookups.html) and attach files via [Uploads](/docs/uploads.html).
Every endpoint follows the shared [Conventions & Errors](/docs/conventions.html) (auth, content
negotiation, pagination, status codes); see [Authentication](/docs/authentication.html) for the
four ways to sign requests.
""",
"endpoints": [
endpoint(
id="messages-inbox",
method="GET",
path="/messages",
title="Open the inbox",
summary="Render conversations. Returns an HTML page.",
auth="user",
interactive=True,
params=[
field(
"with_uid",
"query",
"string",
False,
"",
"Open a specific conversation by user UID.",
),
field(
"search",
"query",
"string",
False,
"",
"Jump to a conversation by username.",
),
],
),
endpoint(
id="messages-send",
method="POST",
path="/messages/send",
title="Send a message",
summary="Send a direct message to a user.",
auth="user",
encoding="form",
destructive=True,
params=[
field(
"content",
"form",
"textarea",
False,
"Hello there.",
"Body, 0-2000 characters. May be empty when at least one attachment is provided.",
),
field(
"receiver_uid",
"form",
"string",
True,
"RECEIVER_UID",
"Recipient user UID.",
),
],
),
endpoint(
id="messages-conversations",
method="GET",
path="/messages/conversations",
title="List conversations",
summary="Return the signed-in user's conversation list as JSON, for live refresh without a full page reload.",
auth="user",
interactive=False,
sample_response={
"conversations": [
{
"other_user": {"uid": "8f14e45f-...", "username": "alice_test"},
"last_message": "Hello there.",
"last_message_at": "2026-07-21T10:00:00+00:00",
"unread": True,
}
]
},
),
endpoint(
id="messages-ws-ticket",
method="POST",
path="/messages/ws-ticket",
title="Issue a WebSocket ticket",
summary="Exchange the caller's session/API-key auth for a short-lived, single-use ticket that a browser WebSocket handshake can carry as a query parameter (a native WebSocket cannot set custom auth headers).",
auth="user",
encoding="none",
interactive=False,
notes=[
"The ticket is valid for 30 seconds and can be redeemed exactly once, as `wss://.../messages/ws?ticket=<ticket>`.",
],
sample_response={"ticket": "3f9c2a...", "expires_in": 30},
),
],
}