Architecture Overview#
Outeract is designed as a unified messaging infrastructure that abstracts the complexity of multiple messaging platforms into a single, consistent API.
System Architecture#
flowchart TB
App["Your Application<br/>Send messages · Query events · Receive webhooks"]
Gateway["API Gateway<br/>Developer API (key) · Console API · Webhook Router"]
Services["Service Layer<br/>Message · Event · Webhook services"]
Adapters["Platform Adapters<br/>WhatsApp · Telegram · Slack · + 7 more"]
Data["Data Layer<br/>PostgreSQL · Event Store · File Storage"]
Ext["External Platform APIs<br/>WhatsApp Cloud · Telegram Bot · Slack Web"]
App --> Gateway
Gateway --> Services
Services --> Adapters
Adapters --> Data
Adapters --> ExtAPI Layer#
Developer API (/)#
- Authentication: API keys with scopes
- Purpose: Message operations, event queries, user management
- Users: Your application backend
This is the API you integrate against. A second, internal GraphQL schema backs the console. It handles account-level operations such as organisations, applications, platform connections, API keys and webhook subscriptions, and authenticates console sessions rather than API keys. It isn’t a public integration surface; anything it manages is configured through the console.
# Developer API Query Example
query {
events(
eventTypes: ["message.inbound", "message.outbound"]
first: 10
) {
edges {
node {
id
eventTypeName
payload
createdAt
}
}
}
}Webhook Architecture#
Outeract uses two webhook patterns depending on the platform:
Shared Webhooks#
Platforms: WhatsApp, Instagram, Facebook Messenger
Multiple platform connections share a single webhook URL. The platform sends all events to one endpoint, and Outeract routes them to the correct connection.
flowchart LR
Meta[Meta Platform] --> Webhook[Shared Webhook]
Webhook --> Router[Route by Account ID]
Router --> WA1[WhatsApp Connection 1<br/>Business Account A]
Router --> WA2[WhatsApp Connection 2<br/>Business Account B]
Router --> IG1[Instagram Connection 1<br/>Page C]Benefits:
- Single webhook URL to configure
- Automatic routing based on payload
- Simplified Meta app setup
Dedicated Webhooks#
Platforms: Telegram, Slack, Discord, SMS, Email
Each platform connection has its own unique webhook URL.
flowchart LR
TG[Telegram] --> TGW["/webhooks/{id}/{secret}"] --> TGC[Telegram Connection 1]
SL[Slack] --> SLW["/webhooks/{id}/{secret}"] --> SLC[Slack Connection 1]
DC[Discord] --> DCW["/webhooks/{id}/{secret}"] --> DCC[Discord Connection 1]Benefits:
- Direct routing (no payload inspection)
- Connection-specific secrets
- Independent configuration
Event Processing Pipeline#
flowchart TB
Msg[Inbound Message] --> WH[Webhook Handler]
WH -- Signature Verification --> PA[Platform Adapter]
PA -- Parse platform-specific payload --> EC[Event Creation]
EC -- Create Event + Edges --> DB[(Database)]
EC --> PS[Pub/Sub Topic]
PS --> Your[Your Webhook Subscription]Multi-Tenancy Model#
Outeract implements strict multi-tenancy at the application level:
flowchart TB
Org[Organisation - Tenant]
Org --> App1[Application 1 - Production]
Org --> App2[Application 2 - Staging]
App1 --> U1[Users - isolated]
App1 --> E1[Events - isolated]
App1 --> PC1[Platform Connections - isolated]
App1 --> K1[API Keys - scoped to this app]
App2 --> U2[Users - isolated]
App2 --> E2[Events - isolated]
App2 --> PC2[Platform Connections - isolated]
App2 --> K2[API Keys - scoped to this app]Isolation guarantees:
- All queries are automatically scoped to the application
- Cross-application data access is impossible
- API keys are bound to specific applications
- Webhooks include application context
Platform Adapters#
Each platform has a dedicated adapter that handles:
| Responsibility | Description |
|---|---|
| Authentication | OAuth flows, token refresh, API keys |
| Message Formatting | Convert to/from platform-specific formats |
| Webhook Processing | Parse inbound payloads, extract messages |
| Error Handling | Translate platform errors to Outeract errors |
| Health Checks | Verify credentials and connectivity |
| Rate Limiting | Platform-specific rate limit handling |
Adapter Interface#
class PlatformAdapter:
async def send_message(message: ExternalMessage) -> SendMessageResult
async def process_webhook(payload: dict) -> List[ExternalMessage]
async def verify_webhook(request: Request) -> Response
async def get_health() -> PlatformConnectionHealth
def validate_signature(request: Request, body: bytes, secret: str) -> boolData Model#
Outeract uses a graph-based data model:
flowchart TB
PU1[Platform User<br/>Sender] -- sent_by --> Event[Event<br/>Message]
Event -- sent_to --> PU2[Platform User<br/>Recipient]
PU1 -- belongs_to --> User[User<br/>Identity]
PU2 -- identity --> User
PU2 -- belongs_to --> PC[Platform Connection]Scalability#
Outeract is designed to scale horizontally:
| Component | Scaling Strategy |
|---|---|
| API Servers | Stateless, load balanced |
| Database | PostgreSQL with read replicas |
| Event Processing | Pub/Sub for async processing |
| File Storage | Google Cloud Storage |
| Webhook Delivery | Queue-based with retries |
Security#
Security is built into every layer:
- Transport: TLS 1.3 for all connections
- Authentication: API keys, console sessions, OAuth 2.0
- Authorization: Scope-based access control
- Webhooks: HMAC-SHA256 signature verification
- Data: Encryption at rest, tenant isolation
- Secrets: Encrypted credential storage