Skip to content

Inbox Filters — cURL Reference

Base URL: https://txpaxbxhnvnhsjwwaeoy.supabase.co

Auth headers (use either): - Authorization: Bearer <SUPABASE_JWT> (user session token) - apikey: <SUPABASE_ANON_KEY> (required by PostgREST)

SUPABASE_URL="https://txpaxbxhnvnhsjwwaeoy.supabase.co"
ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InR4cGF4YnhobnZuaHNqd3dhZW95Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTc1NDQyMzAsImV4cCI6MjA3MzEyMDIzMH0.T2Rj5tc6ThGKQdDUymL3vNT7miiVsjCf4QfQeS_jVNg"
JWT="<your_user_jwt_here>"

All filters are powered by the conversations table + 2 RPCs. RLS automatically scopes results to the caller's organization_id.


1. ALL MESSAGES (no filter)

Returns all conversations for the org, newest first.

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,contact:contacts!conversations_contact_id_fkey(id,first_name,last_name,phones,emails,tags),channel_account:channel_accounts(id,type,name),assignee:profiles!conversations_assignee_id_fkey(id,first_name,last_name)" \
 --data-urlencode "order=last_message_at.desc.nullslast" \
 --data-urlencode "limit=50"

2. UNREAD CONVERSATIONS

Two-step process: get the list of conversation IDs that have unread messages, then fetch their rows.

Step 2a — Get unread counts (RPC)

curl -X POST "$SUPABASE_URL/rest/v1/rpc/get_conversation_unread_counts" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 -H "Content-Type: application/json" \
 -d '{}'

Response:

[
 { "conversation_id": "uuid-1", "unread_count": 3 },
 { "conversation_id": "uuid-2", "unread_count": 1 }
]

Step 2b — Fetch only those conversations

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,contact:contacts!conversations_contact_id_fkey(*),channel_account:channel_accounts(*)" \
 --data-urlencode "id=in.(uuid-1,uuid-2)" \
 --data-urlencode "order=last_message_at.desc"

3. READ CONVERSATIONS

Read = conversations whose IDs are NOT in the unread list. After fetching unread IDs from step 2a, exclude them:

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,contact:contacts!conversations_contact_id_fkey(*),channel_account:channel_accounts(*)" \
 --data-urlencode "id=not.in.(uuid-1,uuid-2)" \
 --data-urlencode "order=last_message_at.desc" \
 --data-urlencode "limit=50"

Alternative (simpler heuristic): last_read_at >= last_message_at

--data-urlencode "or=(last_read_at.gte.last_message_at)"


4. ASSIGNED TO ME

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,contact:contacts!conversations_contact_id_fkey(*),channel_account:channel_accounts(*)" \
 --data-urlencode "assignee_id=eq.<your_user_id>" \
 --data-urlencode "order=last_message_at.desc"

5. UNASSIGNED

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,contact:contacts!conversations_contact_id_fkey(*),channel_account:channel_accounts(*)" \
 --data-urlencode "assignee_id=is.null" \
 --data-urlencode "order=last_message_at.desc"

6. BY STATUS (open / closed / pending)

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "status=eq.open" \
 --data-urlencode "order=last_message_at.desc"

Allowed values: open, pending, resolved, closed.


7. BY CHANNEL TYPE (Instagram, WhatsApp, Messenger, etc.)

Channels live in the channel_accounts table. Filter via embedded resource:

# Get all Instagram channel account IDs first
curl -G "$SUPABASE_URL/rest/v1/channel_accounts" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=id" \
 --data-urlencode "type=eq.INSTAGRAM"

# Then filter conversations
curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,channel_account:channel_accounts!inner(id,type,name)" \
 --data-urlencode "channel_account.type=eq.INSTAGRAM" \
 --data-urlencode "order=last_message_at.desc"

Channel type values: WHATSAPP_LITE, WHATSAPP_CLOUD, MESSENGER, INSTAGRAM, TELEGRAM, TIKTOK, SHOPIFY_INBOX, BULK_EMAIL.


8. INSTAGRAM COMMENTS ONLY

Comments are stored in the same conversations table but flagged with metadata.is_comment_thread = true.

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,channel_account:channel_accounts!inner(id,type,name)" \
 --data-urlencode "channel_account.type=eq.INSTAGRAM" \
 --data-urlencode "metadata->>is_comment_thread=eq.true" \
 --data-urlencode "order=last_message_at.desc"

Instagram DMs only (exclude comments)

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,channel_account:channel_accounts!inner(id,type,name)" \
 --data-urlencode "channel_account.type=eq.INSTAGRAM" \
 --data-urlencode "or=(metadata->>is_comment_thread.is.null,metadata->>is_comment_thread.eq.false)" \
 --data-urlencode "order=last_message_at.desc"

9. FACEBOOK COMMENTS ONLY

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,channel_account:channel_accounts!inner(id,type,name)" \
 --data-urlencode "channel_account.type=eq.MESSENGER" \
 --data-urlencode "metadata->>is_comment_thread=eq.true" \
 --data-urlencode "order=last_message_at.desc"

10. IMPORTANT / STARRED

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "is_important=eq.true" \
 --data-urlencode "order=last_message_at.desc"

11. BY TAG

curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode 'tags=cs.{"vip"}' \
 --data-urlencode "order=last_message_at.desc"

12. SEARCH (by contact name / phone)

# Search contacts then filter conversations by contact_id
curl -G "$SUPABASE_URL/rest/v1/conversations" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 --data-urlencode "select=*,contact:contacts!inner(id,first_name,last_name,phones)" \
 --data-urlencode "contact.full_name_search=ilike.*john*" \
 --data-urlencode "order=last_message_at.desc"

13. UNANSWERED COUNT (sidebar badge)

curl -X POST "$SUPABASE_URL/rest/v1/rpc/get_unanswered_conversations_count" \
 -H "apikey: $ANON_KEY" \
 -H "Authorization: Bearer $JWT" \
 -H "Content-Type: application/json" \
 -d '{}'

Response: 42


Filter Combination Reference

UI Filter Endpoint / Filter
All messages GET /rest/v1/conversations
Unread RPC get_conversation_unread_countsid=in.(...)
Read id=not.in.(unread_ids)
Mine assignee_id=eq.<user_id>
Unassigned assignee_id=is.null
Open / Closed status=eq.open
Instagram (all) channel_account.type=eq.INSTAGRAM
Instagram comments + metadata->>is_comment_thread=eq.true
Instagram DMs + metadata->>is_comment_thread.is.null
Facebook comments channel_account.type=eq.MESSENGER + is_comment_thread=true
WhatsApp channel_account.type=in.(WHATSAPP_LITE,WHATSAPP_CLOUD)
Important is_important=eq.true
Tag tags=cs.{"tag_name"}

Notes: - All requests are RLS-scoped to the caller's organization automatically. - Use !inner joins to filter by embedded resource columns (e.g. channel_account.type). - JSONB fields use ->> for text comparisons (e.g. metadata->>is_comment_thread). - For pagination, append &offset=N&limit=50.