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
conversationstable + 2 RPCs. RLS automatically scopes results to the caller'sorganization_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
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_counts → id=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 |
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.