Sign inSign up

fdciabdul/waxum

By fdciabdul

•Updated about 7 hours ago

WhatsApp REST API gateway in Rust. Multi-device and the official WhatsApp Cloud API

Image
API management
Developer tools
Web servers
1

10K+

fdciabdul/waxum repository overview

Waxum

⁠Waxum

WhatsApp REST API gateway. Written in Rust.

Docs⁠ · API⁠ · Releases⁠


Native single-binary. Multi-session. Multi-DB. Webhooks + HMAC. JWT + Bearer. Swagger. Prometheus. NATS JetStream (optional).

Two WhatsApp providers behind one API. Each session runs on the multi-device protocol (QR / pair code) or on Meta's official WhatsApp Cloud API. Both share the same /messages/* routes and the same webhook events.

Production-grade. 230+ REST endpoints across 34 feature modules.

⁠Features

⁠Messaging
FeatureEndpoint prefix
Text, image, video, audio, document, stickerPOST /sessions/{sid}/messages/*
Location, contact card, pollPOST /sessions/{sid}/messages/{location,contact,poll}
Reactions, forward, edit, revoke, starPOST /sessions/{sid}/messages/{react,forward,edit,delete,star}
Reply / quote with contextPOST /sessions/{sid}/messages/text (quoted_id)
Fake-reply (spoofed quote metadata)POST /sessions/{sid}/fake-reply/*
CTA URL with image + header/footerPOST /sessions/{sid}/messages/cta-url
Broadcast listsPOST /sessions/{sid}/broadcast
Chat state (typing / recording / paused)POST /sessions/{sid}/chat-state
Composing indicator before every sendenv AUTO_PRESENCE_ON_SEND=true, AUTO_PRESENCE_DELAY_MS (default 1200 ms)
Read receipts, mark as readPOST /sessions/{sid}/messages/read
MEX GraphQL passthrough (server queries)POST /sessions/{sid}/mex
Message history + full-text search (SQLite FTS5)GET /sessions/{sid}/messages/search?q=, GET /messages/search?q=
⁠Scheduling & bulk send
FeatureEndpoint
Scheduled send (send_at on all 34 send endpoints)GET/DELETE /sessions/{sid}/scheduled, GET /scheduled
Blast queue (bulk send, pacing, dedup, retry, DLQ)POST /sessions/{sid}/blast, GET /sessions/{sid}/blasts*, GET /blasts
⁠Voice & video calls
FeatureEndpoint
Ring / hangup / accept / rejectPOST /sessions/{sid}/calls/*
Text-to-speech call (Edge TTS, 300+ voices)POST /sessions/{sid}/calls/tts
Audio playback call (MP3/WAV upload or URL)POST /sessions/{sid}/calls/play
Native MLOW codec (WA proprietary, pure Rust)internal
Peer audio recording (WAV)GET /sessions/{sid}/calls/{cid}/recording.wav — local disk by default, S3-compatible object storage (AWS S3, MinIO, R2, …) when S3_BUCKET is set
Bidirectional media WebSocket stream (audio)WS /sessions/{sid}/calls/media/ws?to=&kind=audio
Bidirectional media WebSocket stream (audio + video, H.264)WS /sessions/{sid}/calls/media/ws?to=&kind=av — transport only, bring your own H.264 encoder/decoder (e.g. ffmpeg) on the client side
Transcript of a recording (external whisper.cpp server)POST /sessions/{sid}/calls/{cid}/transcript — needs WHISPER_API_URL; waxum stays a pure-Rust single binary, no C++/whisper.cpp is compiled in
⁠Session management
FeatureEndpoint
Multi-session on one processPOST /sessions
Pair via QR (PNG + SVG)GET /sessions/{sid}/qr, /qr-svg
Pair via 8-char codePOST /sessions/{sid}/pair
Auto-reconnect on startenv WA_AUTO_RECONNECT_ON_START=1
Fleet stats (uptime, per-status counts)GET /stats
Search sessions (name/phone/JID)GET /sessions/search?q=
Bulk purge (by status, older-than, dry-run)POST /sessions/purge
Bulk disconnect / reconnectPOST /sessions/{disconnect,reconnect}-all
Re-enable all tripped webhook circuitsPOST /webhooks/reenable-all
Export / import a session between instances (zip of local storage)POST /sessions/{sid}/export, POST /sessions/{sid}/import
⁠Groups
FeatureEndpoint prefix
Create / leave / info / settingsPOST /sessions/{sid}/groups/*
Member add / remove / promote / demotePOST /sessions/{sid}/groups/{gid}/*
Invite link create / revoke / joinPOST /sessions/{sid}/groups/{gid}/{invite,revoke,join}
Description / subject / picture / announce / lockPATCH /sessions/{sid}/groups/{gid}/*
Pending join requests approvalPOST /sessions/{sid}/groups/{gid}/requests
⁠Contacts / privacy / presence
FeatureEndpoint
is_on_whatsapp batch checkPOST /sessions/{sid}/contacts/check
Contact info + profile pictureGET /sessions/{sid}/contacts/{jid}
Sync device contactsPOST /sessions/{sid}/contacts/sync
Save / rename a contact in the address bookPUT /sessions/{sid}/contacts/{jid}
Block / unblock / list blockedPOST /sessions/{sid}/blocking/*
Privacy settings (last-seen, profile, status)PATCH /sessions/{sid}/privacy
Presence broadcast (online / offline)POST /sessions/{sid}/presence
⁠Media & storage
FeatureEndpoint
Multipart upload (image/video/audio/document)POST /sessions/{sid}/media/upload
Direct URL send (server downloads on your behalf)POST /sessions/{sid}/messages/image?url=
Download inbound media by message idGET /sessions/{sid}/media/{mid}
Media storage on disk (configurable path)env WA_MEDIA_DIR
⁠Webhooks
FeatureEndpoint
Per-session webhook URL + secretPOST /sessions/{sid}/webhooks
HMAC-SHA256 signature (X-Webhook-Signature)header
Event filter mask (message, receipt, call, presence, …)event_mask field
Circuit breaker (auto-trip on Nx 5xx)env WEBHOOK_CB_THRESHOLD
Dead-letter queue + replayGET /sessions/{sid}/webhooks/dlq, POST /sessions/{sid}/webhooks/dlq/{entry_id}/replay
Re-enable all tripped circuits (bulk)POST /webhooks/reenable-all
A message the server redelivers (offline replay, then live) is forwarded onceper session, last 4096 message ids
⁠Ops / observability
FeatureEndpoint
Server-rendered ops console (Handlebars, no SPA)/
Per-session playground covering 60+ endpoints/s/{sid}
Swagger UI + OpenAPI 3.1 schema/swagger-ui
Liveness / readiness probes/livez, /readyz
Prometheus metrics (counters + gauges)/metrics
Session tags (in-memory + JSON snapshot)GET/PUT/POST /api/v1/sessions/{sid}/tags, DELETE .../tags/{tag}, GET /api/v1/tags, GET /api/v1/sessions?tag=
SSE event tail (filter by session / event)GET /api/v1/events/tail
List Edge-TTS voicesGET /api/v1/voices
TTS voice preview (returns MP3)GET /api/v1/tts/preview?text=&voice=
Instance-lock file (single-writer safety)on-boot
FD-limit warning at start (nofile < 65536)on-boot
JWT + static Bearer auth, per-token IP allowlist (planned)header
NATS JetStream event fan-out (optional)env NATS_URL
⁠Storage backends
FeatureNotes
SQLite (default, single-binary friendly)WA_DB=sqlite:///path.db
Postgres (recommended for prod, > 50 sessions)WA_DB=postgres://…
MySQLWA_DB=mysql://…
⁠Known limitations
GapWhy
Group voice callBlocked upstream — whatsapp-rust has no multi-party relay/SFU client at all (single-peer engine only). Not a waxum-side gap; would need its own library-level project in whatsapp-rust first.
Encryption at restNot implemented. libsqlite3-sys (shared with whatsapp-rust-sqlite-storage) would need a bundled-sqlcipher build, which pulls in OpenSSL and breaks single-binary/cross-compile builds. Use OS/disk-level encryption (LUKS, BitLocker, encrypted volumes) instead — the standard approach for encryption at rest, and zero code changes.

⁠Console

Server-rendered ops dashboard baked into the binary. Point a browser at http://<host>:3451/, sign in with your SUPERADMIN_TOKEN, and you land on the fleet overview. Click any session for the per-session playground covering 60+ REST endpoints — send messages, drive calls, manage groups, inspect webhooks, all without leaving the tab.

Waxum Console — fleet overview

Waxum Console — session playground

⁠Install

# Linux / macOS
curl -fsSL https://raw.githubusercontent.com/imtaqin/waxum/main/scripts/install.sh | sudo bash

# Windows (elevated PowerShell)
irm https://raw.githubusercontent.com/imtaqin/waxum/main/scripts/install.ps1 | iex

# Docker
docker pull fdciabdul/waxum

Or build from source:

git clone https://github.com/imtaqin/waxum && cd waxum
cargo build --release
./target/release/waxum
⁠Toolchain

waxum builds on a pinned Rust nightly — nightly-2026-04-05. You do not have to select it: the pin lives in rust-toolchain.toml, and rustup reads that file and installs the right toolchain on your first cargo build. If you have rustup, there is nothing to do.

To install it up front, or to check what you are actually building with:

rustup toolchain install nightly-2026-04-05 --component rustfmt --component clippy
rustup show active-toolchain   # from the repo root; expect nightly-2026-04-05-<host>

Do not run rustup default nightly. That selects a floating latest nightly globally, which is not what this project builds against.

Without rustup, the pin does not apply. rust-toolchain.toml is a rustup feature; a distro-packaged, Homebrew, or Nix cargo ignores it silently — no warning, no error, just a different compiler than the one we test. If a build fails in a way this section does not explain, check cargo --version before anything else.

If you force stable — cargo +stable build — we cannot tell you what happens, because nobody has run it. Historically it failed inside upstream whatsapp-rust with error[E0554]: #![feature] may not be used on the stable release channel⁠, which is the error this pin was introduced to prevent. That cause is gone at the revision we now pin, so a stable build may well succeed — it is simply unverified, and therefore unsupported.

The pin is historical. Upstream whatsapp-rust used the unstable portable_simd feature, which is nightly-only; at the revision waxum currently pins, upstream has removed SIMD from its tree and declares a stable MSRV, and waxum itself uses no unstable features. The pin has not been re-validated against stable, so it stays until someone does that end to end. Tracked in #87⁠.

⁠Dependencies

The WhatsApp protocol layer is not ours. It is whatsapp-rust⁠, a third-party project, and waxum pins eight of its crates to a single git revision rather than to crates.io versions. That is a deliberate choice with real consequences for anyone depending on waxum — including that waxum cannot itself be published to crates.io. The reasoning, the risk, and the bump cadence are written down in docs/DEPENDENCIES.md⁠.

⁠Providers

Each session has a provider:

ProviderConnects viaBest for
whatsapp_web (default)QR code / pair code, the unofficial multi-device protocolPersonal and small-business numbers; groups, calls, channels, polls
whatsapp_cloudMeta's official WhatsApp Cloud API: a WABA plus a system-user tokenVerified business numbers at scale; templates, Flows, commerce, payments

A Cloud session sends and receives through the same /messages/* routes: text, media, location, contact, reaction, buttons, list, and read receipts. Meta's webhooks are normalized into the same message event, so a consumer works unchanged across both providers.

On top of that, a Cloud session gets:

FeatureEndpoint
Attach credentials / Embedded Signup onboardingPOST /sessions/{id}/cloud/connect, /cloud/embedded-signup/exchange
Meta webhook receiver (HMAC X-Hub-Signature-256)GET/POST /sessions/{id}/cloud/webhook
Delivery, read, failed and payment status as structured receipt eventswebhook
Message templates: send, create, edit, delete, list/messages/template, /cloud/templates
WhatsApp Flows: manage, send, encrypted Data Exchange endpoint/cloud/flows, /cloud/flow-endpoint
Commerce: product, multi-product and catalog messages; inbound orders/messages/product, /messages/product-list, /messages/catalog
Payments API (India, Singapore)/messages/order-details, /messages/order-status
Phone number registration, verification, 2FA PIN/cloud/register, /cloud/request-code, /cloud/verify-code
Business profile incl. photo/cloud/business-profile
QR codes, blocked users, typing indicator/cloud/qr-codes, /cloud/blocked-users, /cloud/typing
Analytics, conversation analytics, credit lines/cloud/analytics, /cloud/conversation-analytics
BSP: system users, credit-line sharing/cloud/assigned-users, /cloud/credit-sharing

Full reference: waxum.imtaqin.id/docs/api/cloud⁠.

⁠Endpoints

URLPurpose
/Console — fleet overview + per-session playground
/api/v1REST API
/swagger-uiOpenAPI schema + interactive docs
/livez · /readyzLiveness · readiness probes
/metricsPrometheus text exposition

⁠Stack

Rust nightly · Axum 0.8 · Tokio · whatsapp-rust⁠ · Postgres/MySQL/SQLite · NATS JetStream · Prometheus · Utoipa.

⁠Ecosystem

RepoWhat it is
waxum-studio⁠Visual WhatsApp workflow builder — nodes, integrations, drag-and-drop automation, powered by waxum.
waxum-mcp⁠MCP server for WhatsApp, backed by waxum — send/read/media tools for any MCP client (Claude Desktop, Claude Code, etc).
waxum-channel⁠Claude Code channel plugin — pushes allowlisted WhatsApp messages into a running Claude Code session, replies back, and lets allowlisted senders approve tool calls from WhatsApp.
waxum-sdk⁠TypeScript SDK, types generated from waxum's OpenAPI spec.
waxum-php-client⁠PHP client for the waxum REST API.
waxum-doc⁠Docs site — waxum.imtaqin.id⁠.
waxum-hermes-plugin⁠Hermes Agent⁠ gateway platform plugin — real WhatsApp buttons/lists/CTA-url, which Hermes's built-in Baileys bridge can't do.
waxum-openclaw-plugin⁠OpenClaw⁠ channel plugin — same interactive WhatsApp messaging, wired into OpenClaw's gateway.
waxum-agent⁠Voice-driven WhatsApp assistant on top of waxum — Tauri app (desktop + Android), reads messages aloud and replies by voice via ElevenLabs TTS/STT.

⁠Docs

Everything else — endpoints, webhooks, health probes, deployment, .env reference — lives in the docs:

waxum.imtaqin.id⁠

⁠License

MIT

Tag summary

Content type

Image

Digest

sha256:db236cbab…

Size

24.3 MB

Last updated

about 7 hours ago

docker pull fdciabdul/waxum