Format
emoji|senderId|isSentByMe|order
Example: 😀|@alice:server.com|0|123,👍|@me:server.com|1|124
Setting | Value |
---|---|
Authority | com.beeper.api |
Default Limit | 100 rows (if not specified) |
Required Permissions | READ_PERMISSION , SEND_PERMISSION |
Retrieves a list of chats/conversations.
content://com.beeper.api/chats
Parameter | Type | Description |
---|---|---|
limit | int | Max chats to return Recommended |
offset | int | Pagination offset |
roomIds | string | Comma-separated room IDs |
isLowPriority | 0/1 | Filter low priority chats |
isArchived | 0/1 | Filter archived chats |
isUnread | 0/1 | Filter unread chats |
showInAllChats | 0/1 | Filter visibility |
protocol | string | Filter by protocol (e.g., whatsapp ) |
Column | Type | Description |
---|---|---|
roomId | string | Unique chat identifier |
title | string | Chat display name |
messagePreview | string | Last message preview |
senderEntityId | string | Last message sender |
protocol | string | Network protocol |
isMuted | boolean | Mute status |
unreadCount | int | Number of unread messages |
timestamp | long | Last activity timestamp |
oneToOne | boolean | Direct message flag |
import androidx.core.net.toUri
val cursor = contentResolver.query( "content://com.beeper.api/chats?limit=50&isUnread=1".toUri(), null, null, null, null)
cursor?.use { c -> val roomIdIdx = c.getColumnIndexOrThrow("roomId") val titleIdx = c.getColumnIndexOrThrow("title") val unreadIdx = c.getColumnIndexOrThrow("unreadCount")
while (c.moveToNext()) { val roomId = c.getString(roomIdIdx) val title = c.getString(titleIdx) val unread = c.getInt(unreadIdx) println("$title: $unread unread") }}
Get the total count of chats matching filters.
content://com.beeper.api/chats/count
Same filters as List Chats
val cursor = contentResolver.query( "content://com.beeper.api/chats/count?isUnread=1".toUri(), null, null, null, null)
val count = cursor?.use { if (it.moveToFirst()) { it.getInt(it.getColumnIndexOrThrow("count")) } else 0} ?: 0
Retrieves messages with optional filtering and search.
content://com.beeper.api/messages
Parameter | Type | Description |
---|---|---|
limit | int | Max messages Default: 100 |
offset | int | Pagination offset |
roomIds | string | Comma-separated room IDs |
senderId | string | Filter by sender contact ID |
query | string | Full-text search |
contextBefore | int | Messages before match |
contextAfter | int | Messages after match |
openAtUnread | boolean | Center on first unread |
Column | Type | Description |
---|---|---|
roomId | string | Chat identifier |
originalId | string | Message ID |
senderContactId | string | Sender ID |
timestamp | long | Message timestamp |
isSentByMe | boolean | Sent by current user |
isDeleted | boolean | Deletion status |
type | string | Message type |
text_content | string | Message text |
reactions | string | Encoded reactions |
displayName | string | Sender name |
is_search_match | boolean | Search match flag |
paging_offset | int | Pagination helper openAtUnread only |
last_read | boolean | Read marker openAtUnread only |
// Search with contextval searchTerm = "important"val uri = ("content://com.beeper.api/messages?" + "query=${Uri.encode(searchTerm)}" + "&contextBefore=3&contextAfter=2").toUri()
contentResolver.query(uri, null, null, null, null)?.use { cursor -> val textIdx = cursor.getColumnIndexOrThrow("text_content") val matchIdx = cursor.getColumnIndexOrThrow("is_search_match")
while (cursor.moveToNext()) { val text = cursor.getString(textIdx) val isMatch = cursor.getInt(matchIdx) == 1
if (isMatch) { // This is the matching message println("MATCH: $text") } else { // This is context println("Context: $text") } }}
import androidx.core.net.toUri
val roomId = "!room:server.com"val uri = ("content://com.beeper.api/messages?" + "roomIds=$roomId&openAtUnread=true&limit=50").toUri()
contentResolver.query(uri, null, null, null, null)?.use { cursor -> val textIdx = cursor.getColumnIndexOrThrow("text_content") val offsetIdx = cursor.getColumnIndexOrThrow("paging_offset") val lastReadIdx = cursor.getColumnIndexOrThrow("last_read")
while (cursor.moveToNext()) { val text = cursor.getString(textIdx) val offset = cursor.getInt(offsetIdx) val isLastRead = cursor.getInt(lastReadIdx) == 1 // Center UI around first unread using offset/last_read }}
Get total message count with filters.
content://com.beeper.api/messages/count
val count = contentResolver.query( "content://com.beeper.api/messages/count?roomIds=!room:server.com".toUri(), null, null, null, null)?.use { cursor -> if (cursor.moveToFirst()) { cursor.getInt(cursor.getColumnIndexOrThrow("count")) } else 0} ?: 0
The reactions
column encodes reactions as comma-separated entries:
Format
emoji|senderId|isSentByMe|order
Example: 😀|@alice:server.com|0|123,👍|@me:server.com|1|124
// Parse reactionsval reactionsRaw = cursor.getString(cursor.getColumnIndexOrThrow("reactions")) ?: ""val reactions = reactionsRaw.split(',') .filter { it.isNotEmpty() } .map { part -> val fields = part.split('|') Reaction( emoji = fields.getOrNull(0) ?: "", senderId = fields.getOrNull(1) ?: "", isSentByMe = fields.getOrNull(2) == "1", order = fields.getOrNull(3)?.toLongOrNull() ?: 0 ) }
Send a text message to a chat.
content://com.beeper.api/messages
Parameter | Type | Description |
---|---|---|
roomId | string | Target room ID Required |
text | string | Message body (URL-encoded) Required |
roomId
and messageId
query parametersnull
import android.net.Uriimport androidx.core.net.toUri
val message = "Hello World!"val roomId = "!room:server.com"
val resultUri = contentResolver.insert( ("content://com.beeper.api/messages?" + "roomId=$roomId&text=${Uri.encode(message)}").toUri(), null)
if (resultUri != null) { val sentRoomId = resultUri.getQueryParameter("roomId") val messageId = resultUri.getQueryParameter("messageId") println("Sent message $messageId to $sentRoomId")} else { println("Failed to send message")}
Retrieve contacts with optional filtering.
content://com.beeper.api/contacts
Parameter | Type | Description |
---|---|---|
limit | int | Max contacts Default: 100 |
offset | int | Pagination offset |
senderIds | string | Comma-separated sender IDs |
roomIds | string | Comma-separated room IDs |
query | string | Search display names |
protocol | string | Filter by protocol |
Column | Type | Description |
---|---|---|
id | string | Contact identifier |
roomIds | string | Associated rooms (CSV) |
displayName | string | Display name |
contactDisplayName | string | Alternative name |
linkedContactId | string | Linked contact |
itsMe | boolean | Current user flag |
protocol | string | Network protocol |
val cursor = contentResolver.query( "content://com.beeper.api/contacts?query=John".toUri(), null, null, null, null)
cursor?.use { c -> val idIdx = c.getColumnIndexOrThrow("id") val nameIdx = c.getColumnIndexOrThrow("displayName") val roomsIdx = c.getColumnIndexOrThrow("roomIds")
while (c.moveToNext()) { val contactId = c.getString(idIdx) val name = c.getString(nameIdx) val rooms = c.getString(roomsIdx).split(",")
println("$name is in ${rooms.size} rooms") }}
Get total contact count with filters.
content://com.beeper.api/contacts/count
val count = contentResolver.query( "content://com.beeper.api/contacts/count?protocol=whatsapp".toUri(), null, null, null, null)?.use { cursor -> if (cursor.moveToFirst()) { cursor.getInt(cursor.getColumnIndexOrThrow("count")) } else 0} ?: 0
# Recent unread chatscontent://com.beeper.api/chats?isUnread=1&limit=10
# WhatsApp chats onlycontent://com.beeper.api/chats?protocol=whatsapp
# Search messages for "meeting"content://com.beeper.api/messages?query=meeting
# Active chats (not archived or low priority)content://com.beeper.api/chats?isArchived=0&isLowPriority=0