Open-source Communications Platform as a Service (CPaaS) — SMS, Email, OTP with smart routing and multi-provider failover.
Rust backend (Axum) with waterfall routing — OTP and notifications via email first (cheap/free), SMS fallback only when needed (paid) — saving 60-80% cost. Supports 7 providers with automatic failover.
- Waterfall routing — send OTP/notifications via email first (Resend, free tier), fall back to SMS only when no email available — saving 60-80% cost
- Multi-provider failover — auto-retry with next provider on failure
- 7 providers — Telnyx, Twilio, Plivo (SMS) + Resend, AWS SES, Mailgun, SMTP (Email)
- Batch send — send SMS or Email to multiple recipients in one call
- Webhooks — real-time delivery status notifications with HMAC-SHA256 signatures
- Template engine —
{{variable}}syntax with OTP generation - SDKs — Rust, TypeScript, Java, Go, Python, C
- Billing — Stripe integration with plans, subscriptions, and usage tracking
- Monitoring — Prometheus metrics (
/metrics), JSON logging for Loki, health checks - Test mode —
ch_test_API keys log only, never send real messages - Self-hosted free — MIT license, no billing when self-hosted
use chorus::client::Chorus;
use chorus::types::SmsMessage;
use std::sync::Arc;
let chorus = Chorus::builder()
.add_sms_provider(Arc::new(telnyx))
.add_email_provider(Arc::new(resend))
.default_from_sms("+1234567890".into())
.build();
// Send SMS
let msg = SmsMessage {
to: "+0987654321".into(),
body: "Hello from Chorus!".into(),
from: None,
};
chorus.send_sms(&msg).await?;
// Send OTP via email with SMS fallback
chorus.send_otp("user@example.com", "123456", "MyApp").await?;crates/ # Publishable libraries
├── chorus-core # Traits, routing engine, types, errors (leaf crate)
└── chorus-providers # Telnyx, Twilio, Plivo, Resend, SES, Mailgun, SMTP adapters
services/ # Internal binaries (not published)
└── chorus-server # Axum REST API, billing, dashboard
sdks/
├── rust/ # Native SDK (chorus-rs, re-exports chorus-core + providers)
├── typescript/ # Node.js + Browser (@cntm-labs/chorus)
├── java/ # Java 11+ (com.cntm-labs:chorus)
├── go/ # Go 1.22+ (github.com/cntm-labs/chorus/sdks/go)
├── python/ # Python 3.10+ (chorus-sdk on PyPI)
└── c/ # C11 with libcurl (libchorus)
chorus-server encrypts TOTP secrets at rest with AES-GCM-256. The
key is sourced from the env var CHORUS_ENCRYPTION_KEY and must
decode to exactly 32 bytes. Required at startup; the server panics
if missing or malformed.
Generate a development key:
head -c 32 /dev/urandom | base64Set it in your local .env (or shell):
export CHORUS_ENCRYPTION_KEY="<base64 of 32 bytes>"For production deployments, source the key from your secret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, etc.). Rotating the key is not yet supported — track follow-up B2.2 in the roadmap.
cargo check --workspace # Type check
cargo test --workspace # Run all tests
cargo clippy --workspace -- -D warnings # Lint
cargo fmt --all # Format
# Setup pre-commit hook
git config core.hooksPath .githooksSee CONTRIBUTING.md for guidelines.