hermes - 💡(How to fix) Fix Feature Request: Threema gateway platform adapter

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

Threema fills a gap in Hermes' platform coverage — it's the only major privacy-first messenger (no phone number required, full E2E by default, Swiss jurisdiction) with a real API. Users in the DACH region and privacy-conscious communities use it heavily. Adding it alongside Signal, WhatsApp, and Matrix completes the "privacy messenger" coverage.

Code Example

Files to touch:
  gateway/platforms/threema.pynew file (~500 lines)
  gateway/config.py             ← add THREEMA = "threema" to Platform enum
  gateway/run.py                ← add elif block in _resolve_adapter_for_platform

---

gateway:
  platforms:
    threema:
      enabled: true
      extra:
        gateway_id: "*MYBOT"       # or THREEMA_GATEWAY_ID env var
        api_secret: "abc123..."    # or THREEMA_API_SECRET env var
        private_key_path: "~/.hermes/threema_private.key"
        callback_port: 9000
        callback_host: "0.0.0.0"
RAW_BUFFERClick to expand / collapse

Feature Description

Add a Threema gateway platform adapter so Hermes can send/receive messages through Threema — the privacy-focused Swiss messaging app with full end-to-end encryption.

Threema currently has no adapter. Their Gateway API is production-grade and well-documented, and they maintain an official Python SDK. The integration is architecturally straightforward: a webhook receiver (Threema POSTs callbacks to your server) plus a simple REST sender.

Why This Matters

Threema fills a gap in Hermes' platform coverage — it's the only major privacy-first messenger (no phone number required, full E2E by default, Swiss jurisdiction) with a real API. Users in the DACH region and privacy-conscious communities use it heavily. Adding it alongside Signal, WhatsApp, and Matrix completes the "privacy messenger" coverage.

Technical Research (Complete)

Threema Gateway API

  • Base URL: https://msgapi.threema.ch/
  • Mode: E2E (end-to-end encrypted) — the only mode supporting inbound messages
  • Auth: Per-request from (API identity, 8 chars, e.g. *MYBOT) + secret parameters
  • Official Python SDK: threema.gateway on PyPI (v8.0.0, MIT license, last updated Aug 2024, maintained by Threema)
  • Dependency: Requires libsodium (system-level, not pip) for NaCl box encryption

Endpoints

EndpointMethodPurpose
/send_e2ePOSTSend E2E-encrypted message
/send_e2e_bulkPOSTBatch send (max 1000)
/upload_blobPOSTUpload file/image/audio (max 50 MB)
/blobs/{id}GETDownload blob (1hr TTL after first access)
/creditsGETCheck remaining credits
/pubkeys/{id}GETFetch recipient's public key
/lookup/phone/{n}GETThreema ID by phone number
/lookup/email/{e}GETThreema ID by email
/capabilities/{id}GETCheck recipient capabilities (text,image,video,audio,file)

Message Types (E2E Container)

  • 0x01 — Text (UTF-8, max 3500 bytes)
  • 0x17 — File (JSON metadata + blob reference)
  • 0x10 — Location (lat/lon + optional address)
  • 0x80 — Delivery receipt (received/read/acknowledged/declined)

Inbound: Webhook Callbacks

Threema POSTs application/x-www-form-urlencoded callbacks to your configured URL with fields: from, to, messageId, date, nonce, box (encrypted payload, hex-encoded), mac (HMAC-SHA256 for verification). The box must be decrypted with NaCl using your private key, then the container type determines parsing.

Pricing

  • Free signup, no recurring fees
  • CHF 0.01 per message ($0.011 USD), pay-as-you-go credits
  • 1 credit per send + 1 credit per blob upload (so images cost 2 credits)
  • HTTP 402 when out of credits

Rate Limits

  • HTTP 429 for general rate limiting (no published per-second caps)
  • Max 1000 messages per bulk request
  • Max 1000 hashes per bulk lookup request

Hermes Adapter Interface Mapping

The adapter would follow the standard pattern used by Mattermost, SMS, Matrix, etc.:

Files to touch:
  gateway/platforms/threema.py  ← new file (~500 lines)
  gateway/config.py             ← add THREEMA = "threema" to Platform enum
  gateway/run.py                ← add elif block in _resolve_adapter_for_platform

Required methods (5):

  • __init__(config) — read gateway ID, API secret, private key from config/env
  • connect() — start aiohttp web server for callbacks, verify credentials
  • disconnect() — shut down HTTP server and sessions
  • send(chat_id, text, ...) — POST to /send_e2e
  • get_chat_info(chat_id) — return {"name": ..., "type": "dm"}

Optional rich media overrides (~4):

  • send_image_file() — upload blob → send file message
  • send_voice() — upload blob → send audio
  • send_video() — upload blob → send video
  • send_document() — upload blob → send file

Config in config.yaml:

gateway:
  platforms:
    threema:
      enabled: true
      extra:
        gateway_id: "*MYBOT"       # or THREEMA_GATEWAY_ID env var
        api_secret: "abc123..."    # or THREEMA_API_SECRET env var
        private_key_path: "~/.hermes/threema_private.key"
        callback_port: 9000
        callback_host: "0.0.0.0"

The One Sticky Wart: TLS Requirement

Unlike every other Hermes platform (where Hermes connects OUT to the platform's servers), Threema sends callbacks IN to your server — and it requires a valid, trusted TLS certificate on the callback URL. No self-signed certs. This means users need either:

  • A reverse proxy (nginx/Caddy + Let's Encrypt)
  • A Cloudflare Tunnel
  • ngrok (dev only)

The webhook URL itself must be configured manually in the Threema Gateway admin panel — there's no API endpoint for this. This is a Threema product limitation, not something an adapter can work around.

For a smooth setup experience, the adapter could detect if the configured callback URL has TLS and emit a clear warning if not. The gateway setup wizard (hermes gateway setup) could mention the TLS requirement.

Scope Estimate

~500 lines of new Python, 3 files touched in the Hermes repo. No core changes needed. The official threema.gateway SDK handles all NaCl encryption/decryption. The adapter is simpler than WhatsApp (which juggles Node.js subprocesses) and simpler than Matrix (which runs a WebSocket state machine). It is essentially a webhook receiver + REST sender.

Alternatives Considered

  • Basic mode (send_simple): Server-side encryption, send-only, no inbound messages. Useless for a two-way agent. Ruled out.
  • Third-party bridge (e.g., matterbridge): Adds another moving part and another point of failure. Direct adapter is cleaner.
  • Wait for community: Could sit as a feature request and see if someone picks it up. The research is done and posted here.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING