<img height="1" width="1" style="display:none;" alt="" src="https://px.ads.linkedin.com/collect/?pid=6889170&amp;fmt=gif">
Skip to content
  • There are no suggestions because the search field is empty.

Overview | Chat Projects

This topic covers the scripting API for chat projects. The chat-specific data lives on a separate object model accessed through ChatProjectItem, while the standard document loop still applies for iterating and committing changes.

Common Use Cases

Building custom chat connectors — ReadySuite has built-in connectors for common platforms, but scripts can import data from any chat format. A script reads the source data (CSV, JSON, database, proprietary export), creates participants, conversations, and events through the API, and produces a fully structured chat project. This is the primary way to add support for new or proprietary messaging formats.

Enriching and overlaying existing chat data — Scripts can iterate over an existing chat project to classify messages, flag content, assign importance, update metadata, or populate custom fields. Because each chat event is backed by a DocumentItem, you can combine standard field operations with chat-specific modifications in the same document loop.

Data cleanup and validation — Scripts can audit chat data for integrity issues like missing senders, orphaned threads, or incomplete metadata, and fix or report problems automatically.

Accessing the Chat Project

Use ProjectItem.GetChatProject() to access the chat API. Always check IsChatProject first — calling GetChatProject() on a document project throws a NotSupportedException:

C# Copy
var project = script.GetProject();

if (project.IsChatProject)
{
    var chatProject = project.GetChatProject();
    // Work with chat data
}

Data Model

Chat projects are organized as a hierarchy:

C# Copy
ChatProjectItem
├── Participants (ChatParticipantItem)
└── Sources (ChatSourceItem)
    └── Conversations (ChatConversationItem)
        └── Events (ChatEventItem) ── tied to a DocumentItem
            ├── Reactions (ChatEventReactionItem)
            ├── Attachments (ChatEventAttachmentItem)
            ├── Edits (ChatEventEditItem)
            └── Read Receipts (ChatEventReadReceiptItem)

Participants are global to the project — the same participant can appear in multiple conversations across multiple sources.

Sources are containers of conversations. A project may have one or many sources (e.g. one per data export or platform).

Conversations represent a channel or direct message thread. Each conversation has a type, platform, and its own set of participants.

Events are the individual messages, joins, leaves, or other activities. Each event is tied to a DocumentItem, so you can still use the document loop to iterate them.

Participants

Participants represent the people in a chat project. Each has a unique ID across the entire project.

Creating Participants

C# Copy
var chatProject = script.GetProject().GetChatProject();

var alice = chatProject.CreateParticipant(
    id: "user-001",
    displayName: "Alice Smith",
    email: "alice@example.com");

var bob = chatProject.CreateParticipant(
    id: "user-002",
    displayName: "Bob Jones");

All parameters are optional — omitting id auto-generates a GUID.

Retrieving Participants

C# Copy
var participants = chatProject.GetParticipants();
var alice = chatProject.GetParticipant("user-001");

ChatParticipantItem Properties

Property Type Description
Id string Unique identifier
DisplayName string? Display name
Email string? Email address
AvatarPath string? Path to avatar image
OtherProperties IDictionary<string, string> Custom metadata

Creating a Source and Conversation

C# Copy
var source = chatProject.CreateChatSource();

var conversation = source.CreateConversation(
    id: "general",
    displayName: "General",
    platform: "Slack",
    type: ChatConversationItemType.Channel);

Conversation Types

Value Description
Channel A channel conversation (e.g. Slack channel, Teams channel)
Direct A direct or group message
Other Other or unknown type

Adding Participants to a Conversation

Conversations track which participants are involved. Add participants to the Participants collection:

C# Copy
conversation.Participants.Add(alice);
conversation.Participants.Add(bob);
 
 

 

Setting a Custodian

Each conversation can have a custodian — the person whose perspective the conversation is captured from:

C# Copy
conversation.Custodian = alice;

ChatConversationItem Properties

Property Type Description
Id string Unique within the source
DisplayName string? Conversation name
Platform string Platform identifier (e.g. "Slack", "Teams")
Type ChatConversationItemType Channel, Direct, or Other
Participants ICollection<ChatParticipantItem> Conversation participants
Custodian ChatParticipantItem? Custodian of the conversation
OtherProperties IDictionary<string, string> Custom metadata

Events

Events are the core data in a chat project — messages, joins, leaves, and other activity. Each event is tied to a DocumentItem.

Reading Events from Documents

When iterating documents in a chat project, use GetChatEvent() to access the event tied to each document:

C# Copy
while (script.ReadDocument())
{
    var document = script.Document;
    var chatEvent = document.GetChatEvent();

    if (chatEvent != null)
    {
        var message = chatEvent.Message;
        var sender = chatEvent.Sender;
        var timestamp = chatEvent.Timestamp;
    }
}

GetChatEvent() returns null if the document has no associated chat event.

Creating Events

To create a new event, call CreateChatEvent() on a document. The event is automatically tied to that document:

C# Copy
var newDoc = script.GetNewDocument("MSG-0001");
script.CreateDocument(newDoc);

var chatEvent = newDoc.CreateChatEvent(
    conversation: conversation,
    sender: alice,
    timestamp: DateTime.UtcNow);

chatEvent.Message = "Hello, world!";
script.UpdateDocument(newDoc);

A document can only have one chat event — calling CreateChatEvent() on a document that already has one throws an InvalidOperationException.

Modifying Events

Event properties are mutable. Update them directly and call UpdateDocument():

C# Copy
while (script.ReadDocument())
{
    var document = script.Document;
    var chatEvent = document.GetChatEvent();

    if (chatEvent != null && chatEvent.Type == ChatEventItemType.Message)
    {
        chatEvent.Importance = ChatEventItemImportance.High;
        script.UpdateDocument(document);
    }
}

ChatEventItem Properties

Property Type Description
Id string Unique event identifier
Conversation ChatConversationItem The conversation this event belongs to
Parent ChatEventItem? Parent event (for threaded replies)
Message string? Message content
Type ChatEventItemType Message, Disclaimer, Join, Leave, or Other
Direction ChatEventItemDirection Incoming, Outgoing, or Other
Sender ChatParticipantItem? Who sent the event
Recipients IReadOnlyCollection<ChatParticipantItem> All conversation participants
Timestamp DateTime When the event was sent
Importance ChatEventItemImportance Normal, High, or Other
IsDeleted bool Whether the event was deleted

Event Types

Value Description
Message A chat message
Disclaimer A disclaimer event
Join A participant joined
Leave A participant left
Other Other or unknown event

Threaded Replies

Events can be nested using the Parent property. This is used for threaded replies (e.g. Slack threads):

C# Copy
var reply = newDoc.CreateChatEvent(conversation, bob, DateTime.UtcNow);
reply.Message = "This is a reply.";
reply.Parent = parentEvent;

The parent event must belong to the same conversation. Changing an event's conversation resets Parent to null.

Reactions

Events can have emoji reactions:

C# Copy
var reaction = chatEvent.CreateReaction("👍");
reaction.Count = 3;
reaction.Participants.Add(alice);
reaction.Participants.Add(bob);

 

C# Copy
var reactions = chatEvent.GetReactions();
chatEvent.RemoveReaction(reaction);
chatEvent.ClearReactions();

Attachments

Events can have file attachments or external resource links:

C# Copy
// Local file attachment
var attachment = chatEvent.CreateAttachment("C:\\files\\report.pdf");

// External resource (URL or network path)
var extAttachment = chatEvent.CreateExternalResourceAttachment("https://example.com/file.pdf");

The copyFileToChatSource parameter (default true) controls whether the file is copied into the chat source directory:

C# Copy
var attachment = chatEvent.CreateAttachment(filePath, copyFileToChatSource: false);

ChatEventAttachmentItem Properties

Property Type Description
Id string Unique identifier
DisplayName string? Display name
Path string? Local file path (null for external resources)
IsExternalResource bool Whether this is an external resource
ExternalResourcePath string? External resource path

Attachments can be copied or moved:

C# Copy
attachment.CopyTo("C:\\output\\report.pdf");
attachment.MoveTo("C:\\output\\report.pdf");

Edit History

Track message edits:

C# Copy
var edit = chatEvent.CreateEdit(
    timestamp: DateTime.UtcNow,
    newMessage: "Updated message",
    oldMessage: "Original message",
    participant: alice);

 

C# Copy
var edits = chatEvent.GetEdits();
chatEvent.ClearEdits();

Read Receipts

Track when participants read or received a message:

C# Copy
var receipt = chatEvent.CreateReadReceipt(
    participant: bob,
    timestamp: DateTime.UtcNow,
    type: ChatEventReadReceiptItemType.Read);
Receipt Type Description
Read The message was read
Delivered The message was delivered but may not be read
Other Other or unknown type

Custom Metadata

Most chat types expose an OtherProperties dictionary for storing platform-specific or custom metadata that doesn't fit the standard schema:

C# Copy
participant.OtherProperties["sourceSystem"] = "LegacyChat v2.1";
conversation.OtherProperties["originalId"] = "slack-C123456";

OtherProperties is available on ChatParticipantItem, ChatConversationItem, ChatEventReactionItem, ChatEventAttachmentItem, ChatEventEditItem, and ChatEventReadReceiptItem.

Validation Rules

The chat API enforces several constraints:

  • When setting an event's Conversation, the Sender must be a participant of the target conversation
  • Changing an event's Conversation resets Parent to null
  • A Parent event must belong to the same conversation as the child
  • Participants referenced in reactions, edits, and read receipts must be participants of the event's conversation
  • A document can only have one chat event

Custom Connector (Importing Chat Data)

This example builds a chat project from scratch — the pattern used when writing a custom connector for a format ReadySuite doesn't natively support. The script reads source data, creates the project structure, and ties each message to a document:

C# Copy
public override void Run(IScriptContext script)
{
    base.Run(script);

    var chatProject = script.GetProject().GetChatProject();

    // Create participants
    var alice = chatProject.CreateParticipant(
        id: "user-001", displayName: "Alice Smith", email: "alice@example.com");
    var bob = chatProject.CreateParticipant(
        id: "user-002", displayName: "Bob Jones");

    // Create source and conversation
    var source = chatProject.CreateChatSource();
    var conversation = source.CreateConversation(
        id: "general",
        displayName: "General",
        platform: "CustomChat",
        type: ChatConversationItemType.Channel);

    conversation.Participants.Add(alice);
    conversation.Participants.Add(bob);
    conversation.Custodian = alice;

    // Create a document and event for each message
    var newDoc = script.GetNewDocument("MSG-0001");
    script.CreateDocument(newDoc);

    var chatEvent = newDoc.CreateChatEvent(conversation, alice, DateTime.UtcNow);
    chatEvent.Message = "Hello, team!";
    chatEvent.Direction = ChatEventItemDirection.Outgoing;

    script.UpdateDocument(newDoc);
}

Enriching Existing Chat Data

This example iterates over an existing chat project and flags messages that match a keyword — a common overlay pattern for classification or review workflows:

C# Copy
public override void Run(IScriptContext script)
{
    base.Run(script);

    var project = script.GetProject();
    if (!project.IsChatProject)
    {
        script.AddWarning("This script only works with chat projects.");
        return;
    }

    while (script.ReadDocument())
    {
        var document = script.Document;
        var chatEvent = document.GetChatEvent();

        if (chatEvent == null || chatEvent.Type != ChatEventItemType.Message)
            continue;

        if (!string.IsNullOrEmpty(chatEvent.Message)
            && chatEvent.Message.Contains(options.Keyword, StringComparison.OrdinalIgnoreCase))
        {
            chatEvent.Importance = ChatEventItemImportance.High;
            document.SetFieldData(options.FlagField, "true");
            script.UpdateDocument(document);
        }
    }
}