A minimal-dependency client for the
Matrix Client-Server HTTP API, suitable for
talking to a Synapse or Conduit homeserver from R. Two Imports: curl
and jsonlite. No tidyverse.
Pairs with mx.crypto,
which handles Olm + Megolm; mx.api itself does no cryptography.
# CRAN
install.packages("mx.api")
# GitHub (development version)
remotes::install_github("cornball-ai/mx.api")
library(mx.api)
s <- mx_login(
server = "https://matrix.example",
user = "alice",
password = "hunter2"
)
room <- mx_room_join(s, "#general:matrix.example")
mx_send(s, room, "hello from R")
batch <- mx_sync(s, timeout = 0)
str(batch$rooms$join)
mx_logout(s)
room <- mx_room_create(
s,
name = "project sync",
topic = "weekly check-in",
preset = "private_chat",
invite = c("@bob:matrix.example", "@carol:matrix.example")
)
mx_send(s, room, "kickoff in 5")
mx_room_create returns the new room id as a character string.
Presets: "private_chat", "trusted_private_chat", "public_chat".
mx_send's body is plain text. Matrix clients that show rich text
(Element, Cinny, Fractal, etc.) render the optional formatted_body
field instead, fall back to body when it is absent. Markdown
fences in plain body show as literal backticks; you have to send
HTML in formatted_body to get a real code block.
Pass both via the extra argument:
plain <- "Build steps:\n\ndocker compose build\ndocker compose up -d"
html <- paste0(
"<p>Build steps:</p>",
"<pre><code>docker compose build\n",
"docker compose up -d</code></pre>"
)
mx_send(
s, room, plain,
extra = list(
format = "org.matrix.custom.html",
formatted_body = html
)
)
The format value "org.matrix.custom.html" is the only one the
Matrix spec defines. Supported tags are listed in the
Matrix client-server spec, section 11.2.1.7.
Code blocks use <pre><code>…</code></pre>; inline code is <code>…</code>.
| Area | Functions |
|---|---|
| Session | mx_register, mx_login, mx_logout, mx_whoami, mx_session |
| Rooms | mx_rooms, mx_room_create, mx_room_join, mx_room_leave, mx_room_invite, mx_room_members, mx_room_name, mx_room_topic |
| Messages | mx_send, mx_send_event, mx_messages, mx_sync, mx_react, mx_redact, mx_read_receipt, mx_typing |
| Room state | mx_get_state, mx_set_state |
| Media | mx_upload (streaming), mx_download, mx_send_media (+ mx_send_file / mx_send_image / mx_send_audio / mx_send_video), mx_guess_mime, mx_media_config |
| Profile | mx_profile, mx_set_displayname, mx_set_avatar_url |
| Account data | mx_get_account_data, mx_set_account_data |
| Devices | mx_devices, mx_delete_device |
| E2EE transport | mx_keys_upload, mx_keys_query, mx_keys_claim, mx_send_to_device |
| E2EE signing helper | mx_canonical_json |
End-to-end cryptography is out of scope; pair with mx.crypto
(or another crypto library) to sign and verify the payloads these
endpoints carry. Helpful framing:
vignette("e2ee") walks the whole flow).mx_canonical_json() is the byte-stable encoder Matrix's signing rules
require. It is hand-rolled (not a jsonlite wrapper) so the
spec-sensitive choices — key ordering by UTF-8 byte sequence, integer
range, NaN/Inf/NA rejection, duplicate-key rejection, control-char
escaping — are visible and unit-tested rather than hidden in another
package's defaults.
mx_canonical_json(list(b = 2, a = 1))
#> [1] "{\"a\":1,\"b\":2}"
mx_canonical_json(1.5)
#> Error: mx_canonical_json: non-integer number 1.5 disallowed
107 assertions exercise the encoder (see inst/tinytest/test_canonical_json.R).
0.3.0. Relative to 0.2.0 the delta is additive:
mx_send_event, mx_set_state,
mx_get_state (needed for m.room.encrypted / m.room.encryption).mx_send_media and the file/image/audio/video
wrappers.mx_room_invite, mx_redact, mx_typing,
mx_profile / mx_set_displayname / mx_set_avatar_url.mx_get_account_data, mx_set_account_data.mx_devices, mx_delete_device.mx_error_<ERRCODE>) for programmatic
handling; streamed uploads.See NEWS.md for the full changelog.
GitHub Actions via r-ci; macOS and Ubuntu runners cover every commit + PR.
MIT. See LICENSE.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.