platforms/devplace/rest_messaging.md

DevPlace REST: Direct Messaging

The direct-message endpoints: opening the inbox and a conversation, the read-marking side effect, sending a message with attachments, and the recipient lookup that feeds the composer.

Direct messages between users. The inbox renders HTML; sending uses form fields. Look up recipients with Search & Lookups and attach files via Uploads.

Every endpoint follows the shared Conventions & Errors (auth, content negotiation, pagination, status codes); see Authentication for the four ways to sign requests.

GET /messages - Open the inbox

Render conversations. Returns an HTML page.

Minimal role: Member

Parameters

NameInTypeRequiredDescription
with_uidquerystringnoOpen a specific conversation by user UID.
searchquerystringnoJump to a conversation by username.

Sample response

{
  "conversations": [
    {
      "other_user": {
        "uid": "UID",
        "username": "username",
        "avatar_seed": "string",
        "bio": "text",
        "location": "string",
        "git_link": "string",
        "website": "string",
        "level": 0,
        "xp": 0,
        "xp_progress_pct": 0,
        "xp_next_level": 0,
        "stars": 0,
        "created_at": "2026-01-01T00:00:00+00:00",
        "last_seen": "string"
      },
      "last_message": "string",
      "last_message_at": "string",
      "unread": false
    }
  ],
  "messages": [
    {
      "message": {
        "uid": "UID",
        "sender_uid": "UID",
        "receiver_uid": "UID",
        "content": "text",
        "read": false,
        "created_at": "2026-01-01T00:00:00+00:00"
      },
      "sender": {
        "uid": "UID",
        "username": "username",
        "avatar_seed": "string",
        "bio": "text",
        "location": "string",
        "git_link": "string",
        "website": "string",
        "level": 0,
        "xp": 0,
        "xp_progress_pct": 0,
        "xp_next_level": 0,
        "stars": 0,
        "created_at": "2026-01-01T00:00:00+00:00",
        "last_seen": "string"
      },
      "is_mine": false,
      "time_ago": "2 hours ago",
      "attachments": [
        {
          "uid": "UID",
          "filename": "string",
          "url": "/path",
          "size": 0,
          "is_image": false,
          "is_video": false,
          "mime_type": "string",
          "created_at": "2026-01-01T00:00:00+00:00",
          "can_modify": false
        }
      ],
      "grouped": false
    }
  ],
  "other_user": {
    "uid": "UID",
    "username": "username",
    "avatar_seed": "string",
    "bio": "text",
    "location": "string",
    "git_link": "string",
    "website": "string",
    "level": 0,
    "xp": 0,
    "xp_progress_pct": 0,
    "xp_next_level": 0,
    "stars": 0,
    "created_at": "2026-01-01T00:00:00+00:00",
    "last_seen": "string"
  },
  "current_conversation": "string",
  "search": "string",
  "other_online": false,
  "other_last_seen": "string"
}

POST /messages/send - Send a message

Send a direct message to a user.

Minimal role: Member

Parameters

NameInTypeRequiredDescription
contentformtextareanoBody, 0-2000 characters. May be empty when at least one attachment is provided.
receiver_uidformstringyesRecipient user UID.

Sample response

{
  "ok": true,
  "redirect": "/messages?with_uid=RECEIVER_UID",
  "data": {
    "uid": "MESSAGE_UID"
  }
}

GET /messages/conversations - List conversations

Return the signed-in user's conversation list as JSON, for live refresh without a full page reload.

Minimal role: Member

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
    }
  ]
}

POST /messages/ws-ticket - Issue a WebSocket ticket

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).

Minimal role: Member

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
}