PewPros now includes a unified Conversations API that supports SMS, voice calls, email, and web chat through a single interface. The system can operate standalone or sync bidirectionally with GoHighLevel (GHL) for customers using their Twilio integration.
┌─────────────────────────────────────────────────────────────┐
│ PewPros Mobile App │
│ (pewpros-swift) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ PewPros Conversations API │
│ /api/v1/conversations/* endpoints │
│ ───────────────────────────────────────────────────────── │
│ Pewpros.Conversations context │
│ (source of truth) │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Standalone │ │ GHL Mode │ │ Direct Twilio │
│ (No Provider) │ │ sms_provider │ │ sms_provider │
│ │ │ = "ghl" │ │ = "twilio" │
│ - Local DB │ │ │ │ │
│ - No SMS/Voice │ │ - Sync to GHL │ │ - Direct API │
│ - Web chat OK │ │ - Webhooks in │ │ - Webhooks in │
└─────────────────┘ └─────────────────┘ └─────────────────┘
| Channel | Description | Provider Required |
|---|---|---|
sms |
Text messages | GHL or Twilio |
voice |
Phone calls | GHL or Twilio |
email |
Email threads | Future |
web |
Website chat widget | None (built-in) |
whatsapp |
WhatsApp messages | GHL |
Uses GoHighLevel's Twilio integration. Recommended for customers already using GHL.
Tenant Settings:
sms_provider: "ghl"
ghl_api_key_encrypted: "pit_xxxxx"
ghl_location_id: "loc_xxxxx"Bypasses GHL, talks directly to Twilio API. For customers not using GHL.
Tenant Settings:
sms_provider: "twilio"
twilio_account_sid_encrypted: "ACxxxxx"
twilio_auth_token_encrypted: "xxxxx"
twilio_phone_number: "+15551234567"
twilio_messaging_service_sid: "MGxxxxx" # Optional, for A2P 10DLCSMS/Voice disabled, only web chat works.
sms_provider: nilAll endpoints require authentication via Bearer token.
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/conversations |
List conversations |
POST |
/api/v1/conversations |
Create conversation |
GET |
/api/v1/conversations/:id |
Get conversation + messages |
PUT |
/api/v1/conversations/:id |
Update conversation |
POST |
/api/v1/conversations/:id/assign |
Assign to current user |
POST |
/api/v1/conversations/:id/close |
Close conversation |
POST |
/api/v1/conversations/:id/reopen |
Reopen conversation |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/conversations/:id/messages |
List messages |
POST |
/api/v1/conversations/:id/messages |
Send message in conversation |
POST |
/api/v1/conversations/:id/read |
Mark messages as read |
POST |
/api/v1/conversations/send |
Send to contact/phone (creates conversation) |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/conversations/unread |
Get unread count |
GET /api/v1/conversations?channel=sms&status=open&search=john&limit=50&offset=0
| Param | Description |
|---|---|
channel |
Filter by channel: sms, voice, email, web |
status |
Filter by status: open, closed, archived |
contact_id |
Filter by contact ID |
assigned_to |
Filter by assigned user ID |
search |
Search by name, phone, or email |
limit |
Pagination limit (default 50) |
offset |
Pagination offset |
POST /api/v1/conversations/send
Content-Type: application/json
Authorization: Bearer <token>
{
"contact_id": 123,
"message": "Hello! This is a test message.",
"channel": "sms"
}Response:
{
"data": {
"conversation": {
"id": 456,
"channel": "sms",
"status": "open",
"phone_number": "+15551234567",
"contact": {
"id": 123,
"first_name": "John",
"last_name": "Doe",
"phone": "+15551234567"
}
},
"message": {
"id": 789,
"body": "Hello! This is a test message.",
"direction": "outbound",
"delivery_status": "sent",
"inserted_at": "2026-03-05T20:00:00Z"
},
"status": "sent"
}
}POST /api/v1/conversations/send
{
"phone": "+15559876543",
"message": "Hello from PewPros!",
"channel": "sms"
}POST /api/v1/conversations/456/messages
{
"message": "Thanks for your reply!"
}Configure GHL to send webhooks to:
POST https://your-domain.com/webhooks/ghl
Supported events:
IncomingSMS/sms.inboundIncomingCall/call.inboundCallCompleted/call.completedSMSDelivered/sms.deliveredSMSFailed/sms.failed
Configure Twilio webhooks to:
POST https://your-domain.com/webhooks/twilio
(Webhook controller for direct Twilio to be implemented)
- id: bigint (PK)
- channel: string ("sms", "voice", "email", "web", "whatsapp")
- status: string ("open", "closed", "archived")
- phone_number: string
- visitor_name: string
- visitor_email: string
- visitor_phone: string
- visitor_token: string (for web chat)
- ghl_conversation_id: string (GHL sync)
- contact_id: FK -> contacts
- assigned_to: FK -> users
- last_message_at: datetime
- metadata: jsonb
- inserted_at, updated_at- id: bigint (PK)
- conversation_id: FK -> conversations
- sender_id: FK -> users (nullable)
- sender_type: string ("visitor", "staff", "system")
- body: text
- channel: string
- direction: string ("inbound", "outbound")
- delivery_status: string ("pending", "sent", "delivered", "read", "failed")
- ghl_message_id: string
- call_duration_seconds: integer (for voice)
- recording_url: string (for voice)
- read_at: datetime
- inserted_at, updated_atThe pewpros-swift app includes:
ConversationsViewModel- Full CRUD for conversationsUnifiedConversation/UnifiedMessagemodels- Views for listing, viewing, and composing messages
- Support for all channels with appropriate UI
case conversationsUnified // GET /conversations
case conversationsUnifiedUnread // GET /conversations/unread
case conversationUnified(id: Int) // GET /conversations/:id
case conversationMessages(id: Int) // GET /conversations/:id/messages
case conversationSendMessage(id: Int) // POST /conversations/:id/messages
case conversationAssign(id: Int) // POST /conversations/:id/assign
case conversationCloseUnified(id: Int) // POST /conversations/:id/close
case conversationReopen(id: Int) // POST /conversations/:id/reopen
case conversationMarkRead(id: Int) // POST /conversations/:id/read
case conversationsSend // POST /conversations/sendNew Files:
lib/pewpros/conversations.ex- Main context modulelib/pewpros/integrations/twilio.ex- Direct Twilio clientlib/pewpros_web/controllers/api/v1/conversations_controller.exlib/pewpros_web/controllers/api/v1/conversations_json.exlib/pewpros_web/controllers/webhooks/ghl_webhook_controller.expriv/repo/migrations/*_add_sms_channel_to_conversations.exspriv/repo/migrations/*_add_twilio_fields_to_tenants.exs
Modified Files:
lib/pewpros/chat/conversation.ex- Added channel fieldslib/pewpros/chat/message.ex- Added SMS/voice fieldslib/pewpros/tenants/tenant.ex- Added Twilio fieldslib/pewpros/integrations/ghl.ex- Added Conversations APIlib/pewpros_web/router.ex- Added routes
New Files:
pewpros/Models/UnifiedConversation.swiftpewpros/ViewModels/ConversationsViewModel.swiftpewpros/Views/SMS/SMSConversationsView.swiftpewpros/Views/SMS/SMSDetailView.swiftpewpros/Views/SMS/SMSComposeView.swift
Modified Files:
pewpros/Services/Endpoint.swift- Added conversation endpoints
- Add to MainTabView - Wire SMS view into app navigation
- Admin UI - Add Twilio settings to Site Settings page
- Push Notifications - Notify on inbound SMS
- Direct Twilio Webhooks - Implement webhook controller
- Delivery Status Updates - Poll or webhook for status changes
- Media Messages - MMS support with attachments