Skip to content

Friends ​

Users must be friends before they can start a 1:1 chat. Friendship is mutual: one user sends a request, the other accepts.

Friendship states ​

Search results and user profiles include friendshipStatus from the caller's point of view:

friendshipStatusMeaningAction to show
noneNo relation"Add friend"
outgoing_pendingCaller sent a request"Request sent" / "Cancel"
incoming_pendingThe other user sent a request"Accept" / "Decline"
friendsMutual friends"Message"
selfThe caller—

Blocked users never appear in search, so there is no blocked state there. See Blocking.

            POST /friend-requests                 accept
  none ───────────────────────────▶ pending ───────────────▶ friends
   ▲                                  │                         │
   │   decline / cancel               │                         │ DELETE /friends/{id}
   └──────────────────────────────────┘                         │ or block
   ▲                                                            │
   └────────────────────────────────────────────────────────────┘

Find people ​

GET /users/search?q= ​

  • q starting with +: exact phone match (E.164).
  • Otherwise: username prefix match, case-insensitive, minimum 2 characters.
  • Returns at most 20 results. The caller is excluded.
json
{
  "data": [
    {
      "id": "01JC…",
      "displayName": "Ben Tan",
      "username": "ben_tan",
      "avatarUrl": null,
      "about": "Hey there!",
      "friendshipStatus": "none"
    }
  ],
  "page": { "nextCursor": null, "hasMore": false }
}

phone is never returned in search results.

GET /users/{userId} ​

Profile with friendshipStatus. lastSeenAt and isOnline are included only for friends, and only if the user's privacy setting allows it.

Friend requests ​

POST /friend-requests ​

json
{ "userId": "01JC…" }
SituationResponse
New request201 with FriendRequest (status: "pending"). The other user gets friend_request.received.
The other user already sent you a request200 with FriendRequest (status: "accepted"). You are now friends. Both get friend_request.accepted.
Already friends409 ALREADY_FRIENDS
You already sent a request409 FRIEND_REQUEST_EXISTS
User not found, deleted, or blocked either way404 USER_NOT_FOUND
json
{
  "id": "01JD…",
  "fromUser": { "id": "01JB…", "displayName": "Ana Souza", "username": "ana_souza", "avatarUrl": null },
  "toUser":   { "id": "01JC…", "displayName": "Ben Tan",  "username": "ben_tan",  "avatarUrl": null },
  "status": "pending",
  "createdAt": "2026-10-22T14:04:00.000Z"
}

GET /friend-requests?direction=incoming|outgoing ​

Paginated pending requests, newest first. Use incoming for the Requests screen and the badge count.

POST /friend-requests/{id}/accept ​

Only the recipient. Returns 200 with the new Friend. Both users receive friend_request.accepted.

POST /friend-requests/{id}/decline ​

Only the recipient. 204. The sender is not notified; for them the request simply disappears from outgoing on the next refresh.

DELETE /friend-requests/{id} ​

Only the sender (cancel). 204. The recipient receives friend_request.cancelled.

Friends list ​

GET /friends ​

Paginated, sorted by displayName.

json
{
  "data": [
    {
      "user": {
        "id": "01JC…",
        "displayName": "Ben Tan",
        "username": "ben_tan",
        "avatarUrl": null,
        "about": "Hey there!",
        "isOnline": true,
        "lastSeenAt": "2026-10-22T14:03:11.482Z"
      },
      "since": "2026-10-22T14:05:00.120Z",
      "directConversationId": "01JE…"
    }
  ],
  "page": { "nextCursor": null, "hasMore": false }
}

directConversationId is null until one of you starts a chat.

DELETE /friends/{userId} ​

Removes the friendship for both users. 204. The other user receives friend.removed. The existing conversation stays readable, but new messages fail with 403 NOT_FRIENDS.

Blocking ​

POST /blocks ​

json
{ "userId": "01JC…" }

204. Blocking:

  • Removes the friendship and any pending requests between the two users.
  • Hides each user from the other's search.
  • Stops presence and typing events between them.
  • Makes the other user's sends fail with 403 NOT_FRIENDS.

The blocked user is not notified.

GET /blocks ​

Paginated list of users the caller blocked (for the "Blocked users" settings screen).

DELETE /blocks/{userId} ​

204. Unblocking does not restore the friendship. A new request is needed.

Reporting ​

POST /reports ​

Required by App Store Guideline 1.2.

json
{
  "targetType": "message",
  "targetId": "01JF…",
  "reason": "harassment",
  "comment": "Optional free text"
}

targetType: user or message. reason: spam, harassment, inappropriate, or other. Response 202. Show a confirmation, and offer to block the user.

Real-time events ​

EventReceived byWhen
friend_request.receivedRecipientNew request
friend_request.acceptedBoth usersRequest accepted (including the auto-accept case)
friend_request.cancelledRecipientSender cancelled
friend.removedThe other userFriendship removed
user.updatedAll friendsProfile changed

Payloads are in Real-time.

Questions? Reply to your invitation email.