Skip to main content
spectrum-ts is a unified messaging SDK for TypeScript. Write your logic once, deliver it across every platform — iMessage, WhatsApp Business, your terminal, or a custom platform you build yourself.

Installation

spectrum-ts is the batteries-included package for the standard provider set. The macOS-only local iMessage adapter is intentionally separate so its native Messages database dependencies are never installed in cloud applications.
For a leaner install, depend on @spectrum-ts/core plus only the providers you need:
Either way, the spectrum-ts/providers/<platform> import paths work as long as the matching provider package is installed. Local iMessage is the exception: install and import it explicitly. It has no spectrum-ts/providers/imessage-local compatibility path.
Requires TypeScript 5 or later (TypeScript 6 is also supported).

Core concepts

Spectrum is built around four primitives: Every message arrives as a tuple containing a and a . The space gives you the ability to respond; the message gives you the content and metadata.

Quickstart

Get your credentials

Find your PROJECT_ID and SECRET_KEY in your project Settings on the dashboard. You can pass these to Spectrum(...) directly, or omit them and let Spectrum read SPECTRUM_PROJECT_ID and SPECTRUM_PROJECT_SECRET from the environment. The same explicit-wins-over-env fallback applies to webhookSecret (SPECTRUM_WEBHOOK_SECRET) and to every provider’s config. Provider config fallbacks are automatic and convention-based: any text config field can be supplied through the environment as SPECTRUM_<PLATFORM>_<FIELD>, where <PLATFORM> is the provider’s id upper-cased (spaces and punctuation become _) and <FIELD> is the config key in UPPER_SNAKE_CASE. For example Telegram’s botToken reads from SPECTRUM_TELEGRAM_BOT_TOKEN, and WhatsApp Business’s phoneNumberId reads from SPECTRUM_WHATSAPP_BUSINESS_PHONE_NUMBER_ID. Explicit config always wins over the environment — see the provider setup pages for each field’s env var name.

Run your first app

Projectless providers (like terminal) can be used without credentials:

The app instance

Spectrum() returns a — an object that merges a message stream with platform-specific custom event streams.
app.messages is an AsyncIterable of tuples containing a and a . Custom events emitted by providers are exposed as flat async iterables on the same object — see Custom events and lifecycle. app.webhook() handles both native Spectrum webhooks and Fusor webhooks through the same method. See Webhooks for setup and framework adapters.

Multi-platform in three lines

Combine providers to receive and send across platforms simultaneously:
Messages from every provider merge into the single app.messages stream. The message.platform field identifies the source.

Logging

Spectrum emits structured logs across the core runtime and providers. Control the verbosity with logLevel:
Log output is sanitized — sensitive fields like tokens and secrets are redacted from error attributes before they reach any log destination.

Telemetry

Spectrum has built-in OpenTelemetry instrumentation. Enable it by passing telemetry: true:
When enabled, Spectrum traces initialization, provider setup, message send/receive/get flows, space resolution, and custom events. Each span includes attributes like the provider name, space ID, content type, and sender kind. Traces are sent to the Photon OTLP endpoint by default. Standard OTEL_EXPORTER_OTLP_* environment variables override the default endpoint and headers. Calling app.stop() flushes any pending telemetry data before shutting down.