Messages
Messages are individual WhatsApp messages within a conversation. See Database Schema for the full column reference.
List Messages
const { data } = await sendhub
.from('messages')
.select('id, direction, sender_type, content, delivery_status, confidence, is_draft, created_at')
.eq('conversation_id', convoId)
.order('created_at', { ascending: true })
Send a Message
const { data, error } = await sendhub.from('messages').insert({
conversation_id: convoId,
business_id: workspaceId,
org_id: orgId,
direction: 'outbound',
sender_type: 'agent',
content: 'Your order has shipped!',
}).select('id').single()
For personal (bridge) channels, message delivery is handled automatically through the WhatsApp bridge.
Search Messages
Full-text search across all message content in a workspace:
const { data } = await sendhub
.from('messages')
.select('id, conversation_id, content, sender_type, created_at')
.eq('org_id', orgId)
.ilike('content', `%${query}%`)
.order('created_at', { ascending: false })
.limit(50)
Subscribe to New Messages
const channel = sendhub
.channel('inbox')
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'messages',
filter: `conversation_id=eq.${convoId}`,
}, (payload) => {
console.log('New message:', payload.new)
})
.subscribe()
// Also track delivery status changes
sendhub
.channel('delivery')
.on('postgres_changes', {
event: 'UPDATE',
schema: 'public',
table: 'messages',
filter: `conversation_id=eq.${convoId}`,
}, (payload) => {
console.log('Status:', payload.new.delivery_status)
})
.subscribe()
Delivery Status Flow
pending โ sending โ sent โ delivered โ read
โ failed (retryable)
AI Drafts
When AI confidence is below the channelโs threshold, messages are saved as drafts:
// List drafts awaiting review
const { data: drafts } = await sendhub
.from('messages')
.select('id, content, confidence, created_at')
.eq('is_draft', true)
.eq('business_id', workspaceId)
// Approve and send a draft
await sendhub
.from('messages')
.update({ is_draft: false, delivery_status: 'sending' })
.eq('id', draftId)
// Discard a draft
await sendhub
.from('messages')
.delete()
.eq('id', draftId)