Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 139 additions & 49 deletions apps/web/content/docs/modules/communications.mdx
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
---
title: Communications
description: Unified email, SMS, and push notifications (replaces legacy modules).
agent_summary: "v0.17 unified communications; email/SMS/push via Admin API and grpcSdk; MCP ?modules=communications; Handlebars templates."
description: Unified email, SMS, and push — one module, three channels, orchestrated delivery.
agent_summary: "v0.17 unified communications; Admin /email /push /sms; EmailTemplate + CommunicationTemplate; orchestrator multi-channel/fallback; grpcSdk legacy aliases; MCP ?modules=communications."
---

In **v0.17**, separate **email**, **sms**, and **push-notifications** modules are consolidated into **communications** — one module, one config namespace, three channels.
import CommunicationsDeepDive from "@/mdx/deep-dives/communications-deep-dive.mdx";

Your app needs to reach users on email, push, and SMS — without operating three separate modules, credential sets, and send paths. The **communications** module is the unified messaging layer: one config namespace, channel-specific Admin API routes under `/email`, `/push`, and `/sms` (not `/pushNotifications`), plus orchestration for multi-channel and fallback delivery.

In **v0.17**, legacy **email**, **sms**, and **push-notifications** modules consolidate here. Existing `grpcSdk.email`, `grpcSdk.pushNotifications`, and `grpcSdk.sms` calls continue to work; new integrations can use `grpcSdk.communications` for orchestrated sends. Sending from application runtime stays server-side — never admin credentials in the browser.

## Use cases

<ModuleUseCases
items={[
{
title: "Transactional email",
outcome: "Welcome emails, receipts, password resets via Handlebars templates",
outcome: "Welcome emails, receipts, password resets via Handlebars EmailTemplate",
},
{
title: "Push notifications",
outcome: "FCM device tokens registered from apps; send via Admin API or workers",
outcome: "FCM/OneSignal device tokens registered from apps; send via Admin API or workers",
},
{
title: "SMS & 2FA",
outcome: "Twilio or AWS SNS for verification codes and alerts",
outcome: "Twilio Verify, AWS SNS, or MessageBird for verification codes and alerts",
},
{
title: "Multi-channel orchestration",
outcome: "Fallback chains (email then push) configured admin-side",
outcome: "Broadcast to email + push + SMS, or fallback chains when a channel fails",
},
{
title: "Unified templates",
outcome: "CommunicationTemplate documents coordinate copy across channels for GitOps export",
},
]}
/>
Expand All @@ -33,91 +41,173 @@ In **v0.17**, separate **email**, **sms**, and **push-notifications** modules ar

<ModuleCapabilities
items={[
"Email (SMTP, SendGrid, Mailgun, SES, )",
"Push (FCM, OneSignal, SNS)",
"Email (SMTP, SendGrid, Mailgun, SES, Mandrill, MailerSend)",
"Push (Firebase, OneSignal, Amazon SNS)",
"SMS (Twilio, AWS SNS, MessageBird)",
"Handlebars templates",
"Device token registration",
"Delivery history",
"Orchestration & fallback",
"Handlebars email templates (EmailTemplate CRUD)",
"Multi-channel CommunicationTemplate schema + state export",
"Device token registration & in-app inbox",
"Delivery history (email, SMS records)",
"Orchestration: BEST_EFFORT / ALL_OR_NOTHING broadcast",
"Fallback chains with per-channel timeouts",
"Legacy grpc-sdk aliases (email, pushNotifications, sms)",
]}
/>

## Example: Transactional email + push token
## Example: Template, email send, and fallback

<ModuleExample
steps={[
"Provision WelcomeEmail template via MCP post_email_templates (deploy time)",
"From a custom module or admin script, POST /email/send with templateName and variables",
"App registers FCM token via Client API push routes after user login",
"Send push via Admin API when triggering notifications from server-side code",
"Provision a WelcomeEmail EmailTemplate via Admin API POST /email/templates (deploy time)",
"From server-side code, POST /email/send with templateName and variables",
"App registers FCM token via Client API POST /token after user login",
"For critical alerts, POST /send/fallback with an ordered channel chain",
]}
>
<APIExample
title="Create email template (Admin API — deploy time)"
curl={`curl -X POST http://localhost:3030/email/templates \\
-H "Authorization: Bearer ADMIN_TOKEN" \\
-H "Content-Type: application/json" \\
-d '{"name":"WelcomeEmail","subject":"Welcome {{name}}","body":"<p>Hi {{name}}, welcome aboard.</p>"}'`}
/>
<APIExample
title="Send email (Admin API — server-side only)"
curl={`curl -X POST http://localhost:3030/email/send \\
-H "Authorization: Bearer ADMIN_TOKEN" \\
-H "Content-Type: application/json" \\
-d '{"email":"[email protected]","templateName":"WelcomeEmail","variables":{"name":"Alex"}}'`}
/>
<APIExample
title="Fallback chain (email → SMS)"
curl={`curl -X POST http://localhost:3030/send/fallback \\
-H "Authorization: Bearer ADMIN_TOKEN" \\
-H "Content-Type: application/json" \\
-d '{
"fallbackChain": [
{ "channel": "email", "timeout": 5000 },
{ "channel": "sms", "timeout": 3000 }
],
"recipient": "[email protected]",
"subject": "Security alert",
"body": "Suspicious sign-in detected",
"variables": { "code": "482910" }
}'`}
/>
</ModuleExample>

## How it works

<ModuleDeepDive>
### API surfaces
<CommunicationsDeepDive />
</ModuleDeepDive>

| Layer | Role |
|-------|------|
| **Client API** | Device token registration, in-app notification inbox |
| **Admin API** | Send email/push/SMS, template CRUD, delivery history |
| **gRPC / grpc-sdk** | Server-side sending from custom modules (`grpcSdk.email`, etc.) |
## Configure

Legacy grpc-sdk client names (`grpcSdk.email`, `grpcSdk.pushNotifications`, `grpcSdk.sms`) route to communications automatically.
Patch via MCP `patch_config_communications` (`?modules=communications` or aliases `email`, `push`, `sms`):

| Key | Default | Meaning |
|-----|---------|---------|
| `email.active` | `false` | Enable email channel |
| `email.transport` | `smtp` | Provider: `smtp`, `sendgrid`, `mailgun`, `amazonSes`, `mandrill`, `mailersend` |
| `email.sendingDomain` | `conduit.com` | Appended to bare sender names |
| `email.storeEmails.enabled` | — | Persist sent email records for resend/history |
| `pushNotifications.active` | `false` | Enable push channel |
| `pushNotifications.providerName` | — | `firebase`, `onesignal`, `amazonSns` |
| `sms.active` | `false` | Enable SMS channel |
| `sms.providerName` | `twilio` | `twilio`, `awsSns`, `messageBird` |
| `sms.twilio.verify.active` | `false` | Twilio Verify for OTP flows |
| `orchestration.retryAttempts` | `3` | Retries per channel send |
| `orchestration.fallbackTimeout` | `5000` | Default fallback step timeout (ms) |

### Templates
## Client API

Email templates use Handlebars (`{{variableName}}`) in subject and body. Variables are extracted on create. Reference `templateName` when sending — provision templates at deploy time, not from app runtime.
Push and in-app notification routes (authenticated). Served at the router root (no module prefix):

### Migration from v0.16
| Method | Path | Purpose |
|--------|------|---------|
| POST | `/token` | Register device token `{ token, platform }` |
| DELETE | `/token` | Clear tokens; optional `?platform=` |
| GET | `/notifications` | In-app inbox (`read`, `skip`, `limit`, `platform`) |
| PATCH | `/notifications` | Mark read `{ id }` or `{ before }` |

Standalone email, sms, and push-notifications modules are replaced. MCP aliases `?modules=email,push,sms` still work. See [Migration guide](/docs/resources/migration-v0.16-to-v0.17).
</ModuleDeepDive>
**Sending** email, SMS, or push is Admin API or grpc-sdk only — not from browser-exposed app code.

## Configure
## Admin API

MCP: `?modules=communications` (aliases: `email`, `push`, `sms`).
All routes require Admin API authentication. Default Admin port: `3030`. Paths use `/email`, `/push`, `/sms` — never `/pushNotifications`.

| Tool | Purpose |
|------|---------|
| `get_config_communications` | Read email, push, SMS, orchestration |
| `patch_config_communications` | Provider credentials and channel settings |
| `post_email_templates` | Create Handlebars template |
### `/email`

Config nests `email`, `pushNotifications`, `sms`, and `orchestration` under the communications key.
| Method | Path | Purpose |
|--------|------|---------|
| POST | `/email/send` | Send — `templateName` or inline `subject` + `body` |
| GET | `/email/templates` | List EmailTemplates (`skip`, `limit`, `sort`, `search`) |
| POST | `/email/templates` | Create EmailTemplate |
| PATCH | `/email/templates/:id` | Update EmailTemplate |
| DELETE | `/email/templates/:id` | Delete EmailTemplate |
| GET | `/email/templates/external` | List provider-managed templates |
| POST | `/email/templates/external/sync` | Sync external templates into Conduit |
| POST | `/email/resend` | Resend by email record `{ id }` |
| GET | `/email/emails` | Sent email history |
| GET | `/email/emails/:id` | Single email record |

### `/push`

## Client API
| Method | Path | Purpose |
|--------|------|---------|
| POST | `/push/send` | Send — `userId`, `title`, `body`, optional `data`, `platform`, `isSilent`, `doNotStore` |
| GET | `/push/tokens` | List device tokens |
| GET | `/push/tokens/:id` | Single token |
| DELETE | `/push/tokens/:id` | Remove token |

Push and in-app notification routes (authenticated). v0.17 unified communications serves these at the router root (no module prefix):
### `/sms`

| Method | Path | Purpose |
|--------|------|---------|
| POST | `/token` | Register FCM/device token `{ token, platform }` |
| DELETE | `/token` | Clear tokens; optional `?platform=` |
| GET | `/notifications` | In-app inbox (`read`, `skip`, `limit`, `platform`) |
| PATCH | `/notifications` | Mark read `{ id }` or `{ before }` |
| POST | `/sms/send` | Send SMS — `to`, `message` |
| GET | `/sms/messages` | Sent SMS history |
| GET | `/sms/messages/:id` | Single SMS record |

**Sending** email/SMS/push is Admin API or grpc-sdk — not from browser-exposed app code with admin credentials.
### Orchestrator (`/send`)

| Method | Path | Purpose |
|--------|------|---------|
| POST | `/send/multiple` | Multi-channel broadcast — `channels`, `strategy`, `recipient`, `subject?`, `body?`, `variables?` |
| POST | `/send/fallback` | Fallback chain — `fallbackChain[{ channel, timeout }]`, `recipient`, `subject?`, `body?`, `variables?` |

### CommunicationTemplate (GitOps)

Multi-channel **CommunicationTemplate** documents have no dedicated Admin REST CRUD yet. Manage via [state export/import](/docs/guides/gitops-state-export) (`communicationTemplates`), direct database provisioning, or gRPC `RegisterCommunicationTemplate` from server-side workers (placeholder until unified template CRUD is complete).

## grpc-sdk

| Client | Use when |
|--------|----------|
| `grpcSdk.email` | Legacy email send, template register, status — routes to communications |
| `grpcSdk.pushNotifications` | Legacy push send, token management |
| `grpcSdk.sms` | Legacy SMS send, Twilio Verify |
| `grpcSdk.communications` | Unified API: `sendMessage`, `sendToMultipleChannels`, `sendWithFallback`, `getMessageStatus` |

Never import grpc-sdk in client components or browser bundles.

## MCP

- `?modules=communications`
- Aliases: `?modules=email,push,sms`
- Note: `push-notifications` is not a valid MCP alias — use `push` or `communications`
- `?modules=communications` — full module tools and config
- Aliases: `?modules=email`, `?modules=push`, `?modules=sms`, or `?modules=email,push,sms`
- **Invalid:** `push-notifications` — use `push` or `communications`

| Tool | Purpose |
|------|---------|
| `get_config_communications` | Read email, push, SMS, orchestration settings |
| `patch_config_communications` | Provider credentials and channel toggles |
| `post_email_templates` | Create Handlebars EmailTemplate |

<NextSteps steps={[
{ title: "Migration from v0.16", href: "/docs/resources/migration-v0.16-to-v0.17" },
{ title: "GitOps state export", href: "/docs/guides/gitops-state-export" },
{ title: "Authentication (2FA, verify email)", href: "/docs/modules/authentication" },
{ title: "Legacy docs (email module)", href: "/docs/resources/legacy-docs" },
{ title: "Chat (invite email/push)", href: "/docs/modules/chat" },
{ title: "Admin API reference", href: "/docs/reference/admin-api" },
{ title: "MCP tools", href: "/docs/reference/mcp-tools" },
]} />
131 changes: 131 additions & 0 deletions apps/web/src/mdx/deep-dives/communications-deep-dive.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
### Unified module, channel-scoped Admin paths

One **communications** module owns all three channels. Admin routes register at the **router root** — there is no `/communications` prefix:

| Prefix | Purpose |
|--------|---------|
| `/email/*` | Send, templates, delivery history, resend |
| `/push/*` | Send notifications, manage device tokens — **not** `/pushNotifications` |
| `/sms/*` | Send SMS, delivery history |
| `/send/*` | Orchestrator — multi-channel broadcast and fallback |

Config nests push settings under `pushNotifications` (legacy key name); Admin API paths use `/push`.

### API surfaces

| Layer | Role |
|-------|------|
| **Client API** | Device token registration, in-app notification inbox (router root, no prefix) |
| **Admin API** | Send email/push/SMS, template CRUD, delivery history, orchestration |
| **gRPC / grpc-sdk** | Server-side sending from custom modules (`grpcSdk.email`, `grpcSdk.communications`, …) |

Legacy grpc-sdk clients (`grpcSdk.email`, `grpcSdk.pushNotifications`, `grpcSdk.sms`) route to communications automatically.

### Templates: EmailTemplate vs CommunicationTemplate

**EmailTemplate** — email-only Handlebars templates. Full Admin CRUD at `/email/templates`. Variables are auto-extracted from `{{placeholders}}` in subject and body on create. Reference by **`templateName`** when calling `POST /email/send` or `grpcSdk.email.sendEmail`.

| Field | Purpose |
|-------|---------|
| `name` | Unique identifier — used as `templateName` when sending |
| `subject`, `body` | Handlebars strings |
| `variables` | Auto-derived from `{{…}}` placeholders |
| `sender` | Optional override sender |
| `externalManaged` | Sync with SendGrid/Mailgun provider templates |

**CommunicationTemplate** — unified multi-channel template stored in the database. One document covers every channel the message uses:

| Field | Purpose |
|-------|---------|
| `name` | Unique template identifier |
| `channels` | `['email', 'push', 'sms']` — which channels this template serves |
| `email` | `{ subject, body, sender? }` — Handlebars in subject/body |
| `push` | `{ title, body }` — `{{variable}}` interpolation |
| `sms` | `{ message }` — `{{variable}}` interpolation |
| `variables` | Declared variable names shared across channels |

CommunicationTemplate documents are **exportable/importable** via [state export](/docs/guides/gitops-state-export) (`communicationTemplates` resource type). Provision at deploy time alongside EmailTemplates.

For **EmailTemplate**, use Admin REST (`POST /email/templates`) or MCP `post_email_templates`. For **CommunicationTemplate**, prefer GitOps state import or direct database provisioning today. gRPC `RegisterCommunicationTemplate` is the orchestrator registration hook (server-side grpc-sdk only); it currently returns a minimal placeholder response — full unified Admin REST CRUD for CommunicationTemplate is not exposed yet.

### Sending with `templateName`

| Path | `templateName` behavior |
|------|-------------------------|
| `POST /email/send` | Resolves **EmailTemplate** by name; compiles Handlebars with `variables`. Omit only when providing inline `subject` + `body`. |
| `grpcSdk.email.sendEmail(templateName, …)` | Same resolution as Admin API |
| `POST /send/multiple`, `POST /send/fallback` | Inline `subject`, `body`, `variables` per channel — **no** `templateName` lookup on REST |
| gRPC `SendToMultipleChannels`, `SendWithFallback` | Accept `templateName` in the proto for CommunicationTemplate resolution |
| `POST /push/send`, `POST /sms/send` | Inline `title`/`body` or `message` — no template lookup |

```typescript
// Email — template by name (server-side only)
await grpcSdk.email!.sendEmail("WelcomeEmail", {
email: "[email protected]",
variables: { name: "Alex" },
});

// Orchestrator — multi-channel broadcast
await grpcSdk.communications!.sendToMultipleChannels(
["email", "push"],
"BEST_EFFORT",
{
recipient: "[email protected]",
subject: "Order shipped",
body: "Your order {{orderId}} is on the way",
variables: { orderId: "ORD-42" },
}
);
```

### Orchestration

The orchestrator coordinates delivery across channels through two Admin API entry points:

| Admin route | Strategy | Behavior |
|-------------|----------|----------|
| `POST /send/multiple` | `BEST_EFFORT` or `ALL_OR_NOTHING` | Parallel send to listed channels; `ALL_OR_NOTHING` fails if any channel fails |
| `POST /send/fallback` | Ordered chain | Try each channel in sequence with per-step `timeout` (ms) until one succeeds |

`POST /send/multiple` returns `{ successCount, failureCount, results[] }`. `POST /send/fallback` returns `{ successfulChannel, messageId, attempts[] }`.

Orchestration config (`retryAttempts`, `retryDelay`, `timeout`, `fallbackTimeout`) lives under `communications.orchestration`.

### Migration from v0.16

Standalone **email**, **sms**, and **push-notifications** modules are deprecated. Communications is a drop-in replacement:

1. **Deploy** — register `Communications` instead of three separate modules.
2. **Config** — nest legacy keys under `communications` (example below).
3. **Code** — existing `grpcSdk.email`, `grpcSdk.pushNotifications`, `grpcSdk.sms` calls continue unchanged.
4. **MCP** — use `?modules=communications` or aliases `?modules=email,push,sms`. `push-notifications` is **not** a valid alias.

```yaml
communications:
active: true
email:
active: true
transport: sendgrid
sendingDomain: example.com
transportSettings:
sendgrid:
apiKey: "…"
pushNotifications: # config key — Admin paths use /push
active: true
providerName: firebase
firebase:
projectId: "…"
sms:
active: true
providerName: twilio
twilio:
accountSID: "…"
authToken: "…"
orchestration:
retryAttempts: 3
fallbackTimeout: 5000
```

On first boot, communications can auto-merge legacy top-level `email`, `pushNotifications`, and `sms` config into the unified namespace when channel values still match defaults. Legacy gRPC service names are preserved on the unified `Communications` gRPC service.

See [Migration guide](/docs/resources/migration-v0.16-to-v0.17).
Loading