Skip to main content

Communication Data Model

Communication manages three primary entities: Channels, Registrations, and Deliveries. IDs use prefixed formats for quick identification.

CommunicationChannel

A configured messaging endpoint backed by a provider.

interface CommunicationChannel {
id: string; // "ch_" + nanoid(12)
name: string; // Unique channel name
provider: CommunicationProvider; // Provider type
description?: string;
status: ChannelStatus; // "active" | "disabled"
config: Record<string, unknown>; // Provider-specific configuration
createdAt: string; // ISO 8601
updatedAt: string; // ISO 8601
}

type CommunicationProvider =
| "resend" | "slack" | "telegram"
| "whatsapp" | "webhook" | "custom";

type ChannelStatus = "active" | "disabled";

Config Examples

// Resend (email)
{ "apiKey": "env:RESEND_API_KEY", "fromAddress": "noreply@example.com" }

// Slack
{ "webhookUrl": "env:SLACK_WEBHOOK_URL" }

// Telegram
{ "botToken": "env:TELEGRAM_BOT_TOKEN", "chatId": "-100123456789" }

// Webhook
{ "url": "https://example.com/hook", "headers": { "X-Auth": "env:WEBHOOK_SECRET" } }

ChannelRegistration

An application's connection to a channel.

interface ChannelRegistration {
id: string; // "reg_" + nanoid(12)
appId: string; // Application identifier
channelId: string; // Channel ID
target: string; // Default recipient (email, channel name, etc.)
metadata?: Record<string, string>; // Additional context
enabled: boolean; // Whether the registration is active
createdAt: string; // ISO 8601
updatedAt: string; // ISO 8601
}

CommunicationDelivery

A record of a sent (or attempted) message.

interface CommunicationDelivery {
id: string; // "dl_" + nanoid(12)
appId: string; // Application that sent the message
channelId: string; // Channel used
registrationId?: string; // Registration used for routing
provider: string; // Provider that handled delivery
target: string; // Recipient address
status: DeliveryStatus; // "accepted" | "failed"
subject?: string; // Message subject (email)
text?: string; // Plain text body
html?: string; // HTML body (email)
providerMessageId: string; // ID from the provider
live: boolean; // Whether actually sent (false = dry-run)
details?: unknown; // Provider-specific response details
metadata?: Record<string, string>;
createdAt: string; // ISO 8601
errorMessage?: string; // Error details on failure
}

type DeliveryStatus = "accepted" | "failed";

SendPayload

The request body for sending a message.

interface SendPayload {
channelId: string; // Required: which channel to use
registrationId?: string; // Optional: specific registration (auto-resolved if omitted)
to?: string; // Optional: override target from registration
subject?: string; // Message subject
text?: string; // Plain text body (at least text or html required)
html?: string; // HTML body
metadata?: Record<string, string>;
}

Storage

File-Based (SHIFT_STORAGE=file)

.communication/
store.json # All channels, registrations, and deliveries in a single file

Gateway-Backed (SHIFT_STORAGE=gateway)

CLI routes all operations through the gateway REST API. No local storage.