Skip to main content
New Expensify brings chat directly into the heart of expense management, making collaboration seamless and contextual. Every expense, report, and workspace has an integrated chat thread where team members can discuss details, ask questions, and get approvals in real-time.

What Makes New Expensify Chat Different?

Unlike traditional expense tools that bolt on chat as an afterthought, New Expensify was built from the ground up around conversations:

Context-Aware

Every chat is tied to a specific expense, report, or workspace, keeping conversations organized and relevant.

Real-Time Sync

Messages appear instantly across all devices with optimistic updates for offline work.

Rich Formatting

Use markdown, mentions, and reactions to communicate effectively.

Task Management

Create and assign tasks directly in chat to keep projects moving.

Chat Types

New Expensify supports multiple types of conversations:

1-on-1 Chats

Direct messages between two team members for private discussions about expenses, approvals, or general communication.
1-on-1 chats are automatically created when you assign a task or need to discuss an expense with a specific person.

Group Chats

Multi-person conversations for team discussions, project coordination, or departmental communication.
// From src/libs/ReportUtils.ts
function buildOptimisticGroupChatReport(
    participantList: number[],
    reportName: string,
    avatarUri: string,
    optimisticReportID: string,
    notificationPreference: NotificationPreference,
    isOwnPolicyExpenseChat = false,
): OptimisticChatReport {
    const currentTime = DateUtils.getDBTime();
    return {
        reportID: optimisticReportID,
        chatType: CONST.REPORT.CHAT_TYPE.GROUP,
        reportName,
        avatarUri,
        participants: participantList.reduce((acc, accountID) => {
            acc[accountID] = {
                notificationPreference,
            };
            return acc;
        }, {} as Participants),
        lastReadTime: currentTime,
        lastVisibleActionCreated: currentTime,
    };
}

Workspace Rooms

Dedicated chat rooms for workspaces with special types:
  • #admins: Private room for workspace administrators
  • #announce: Broadcast channel for important workspace announcements
  • #general: Main workspace discussion room

Report Threads

Every expense report has its own chat thread where approvers and submitters can discuss line items, request clarification, or coordinate approvals.

Key Features

Offline-First Architecture

Chats work seamlessly even when offline, with optimistic updates that sync automatically when you reconnect:
// Optimistic message creation from src/libs/actions/Report/index.ts
const optimisticReportAction = buildOptimisticAddCommentReportAction(
    reportComment,
    file,
    transaction,
);

// Message appears immediately in UI
Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
value: {[optimisticReportAction.reportActionID]: optimisticReportAction},
Optimistic updates mean your messages appear instantly, even before the server confirms them. If you’re offline, they’ll sync automatically when your connection returns.

Reactions and Emoji

React to messages with emoji to acknowledge comments without adding clutter:
// Adding emoji reactions from src/libs/actions/Report/index.ts
function addEmojiReaction(
    reportID: string,
    reportActionID: string,
    emoji: Emoji,
    skinTone: number = -1,
) {
    const parameters: AddEmojiReactionParams = {
        reportID,
        reportActionID,
        emoji: emoji.name,
        skinTone,
    };
    
    API.write(WRITE_COMMANDS.ADD_EMOJI_REACTION, parameters, {
        optimisticData,
        successData,
        failureData,
    });
}

File Attachments

Share receipts, documents, and images directly in chat:
  • Drag and drop files into the chat
  • Take photos directly from mobile devices
  • Preview images and PDFs inline

Search and Filters

Quickly find conversations using the global search:
  • Search by participant name
  • Filter by chat type (1-on-1, group, workspace)
  • Search message content
  • Filter by date range

Architecture Insights

Real-Time Updates with Pusher

New Expensify uses Pusher for real-time message delivery:
// Pusher typing indicators from src/libs/actions/Report/index.ts
function broadcastUserIsTyping(reportID: string) {
    const privateUserChannelName = `private-user-accountID-${currentUserAccountID}`;
    const typingStatus: UserIsTypingEvent = {
        [reportID]: true,
    };
    Pusher.sendEvent(privateUserChannelName, Pusher.TYPE.USER_IS_TYPING, typingStatus);
}

State Management with Onyx

Chats are stored locally using Onyx (React Native’s state management):
// Chat storage structure
ONYXKEYS.COLLECTION.REPORT // Chat metadata
ONYXKEYS.COLLECTION.REPORT_ACTIONS // Individual messages
ONYXKEYS.COLLECTION.REPORT_METADATA // UI state (isLoadingMore, etc.)

Best Practices

Use the chat thread attached to each expense or report rather than starting separate conversations. This keeps all relevant information in one place.
@mention specific people when you need their attention. This sends them a notification and highlights the message.
Convert discussion points into actionable tasks by creating them directly in the chat. This ensures follow-through.
Don’t worry about connectivity—compose messages offline and they’ll send automatically when you reconnect.

Next Steps

Messaging & Threads

Learn about composing messages, formatting text, and managing conversation threads

Task Management

Discover how to create and manage tasks within chat conversations

Mentions & Notifications

Master @mentions and notification preferences

Offline-First Architecture

Understand how offline-first chat works under the hood

Build docs developers (and LLMs) love