## Update a conversation **patch** `/v2/conversations/{id}` Updates a conversation's properties. Supports partial updates - only provided fields will be updated. ### Path Parameters - `id` - The conversation ID (short ID) ### Request Body All fields are optional. Only provided fields will be updated. | Field | Type | Description | | ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------- | | `actingAdminId` | string | Admin ID performing the action (for attribution). If not provided, uses bot service user. Must be a member of the organization. | | `state` | string | Conversation state: "open", "closed", or "snoozed" | | `snoozedUntil` | string | ISO datetime when to unsnooze (required when state is "snoozed") | | `adminAssigneeId` | string/null | Admin ID to assign, or null to unassign | | `teamAssigneeId` | string/null | Team ID to assign, or null to unassign | | `title` | string | Conversation title | | `customAttributes` | object | Custom attributes to set on the conversation | | `markAsRead` | object | Mark conversation as read for specific users | ### markAsRead Object | Field | Type | Description | | ------------- | -------- | -------------------------------------------------------------- | | `allAdmins` | boolean | If true, marks all admins with existing readReceipts as read | | `adminIds` | string[] | Array of specific admin IDs to mark as read | | `allContacts` | boolean | If true, marks all contacts with existing readReceipts as read | | `contactIds` | string[] | Array of specific contact IDs to mark as read | Note: Only users with existing read receipts will be updated. Use `allAdmins`/`allContacts` OR `adminIds`/`contactIds` - the "all" flags take precedence. ### Response Returns the updated conversation object. ### Example: Close a Conversation (with attribution) ```json { "actingAdminId": "507f1f77bcf86cd799439011", "state": "closed" } ``` ### Example: Close a Conversation (bot user) ```json { "state": "closed" } ``` ### Example: Snooze a Conversation ```json { "state": "snoozed", "snoozedUntil": "2025-01-20T10:00:00.000Z" } ``` ### Example: Assign to an Admin ```json { "adminAssigneeId": "507f1f77bcf86cd799439011" } ``` ### Example: Update Title and Custom Attributes ```json { "title": "Billing Issue - Priority", "customAttributes": { "priority_level": "high", "category": "billing" } } ``` ### Example: Mark as Read (All Admins) ```json { "markAsRead": { "allAdmins": true } } ``` ### Example: Mark as Read (All Contacts) ```json { "markAsRead": { "allContacts": true } } ``` ### Example: Mark as Read (Specific IDs) ```json { "markAsRead": { "adminIds": ["507f1f77bcf86cd799439011"], "contactIds": ["676f0f6765bdaa7d7d760f88"] } } ``` ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. ### Path Parameters - `id: string` Conversation ID (short ID) ### Header Parameters - `"Featurebase-Version": optional "2026-01-01.nova" or "2025-12-12.clover"` - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Body Parameters - `actingAdminId: optional string` The admin ID performing this action. Changes will be attributed to this admin. If not provided, changes are attributed to the system bot user. The admin must be a member of the organization. - `adminAssigneeId: optional string` The admin ID to assign the conversation to, or null to unassign. - `customAttributes: optional map[unknown]` Custom attributes to set on the conversation. Uses the same validation as v1 API. - `markAsRead: optional object { adminIds, allAdmins, allContacts, contactIds }` Mark the conversation as read for specific admins and/or contacts. - `adminIds: optional array of string` Array of admin IDs to mark as read. Only admins with existing readReceipts will be updated. - `allAdmins: optional boolean` If true, marks all admins with existing readReceipts as read. - `allContacts: optional boolean` If true, marks all contacts (customers and leads) with existing readReceipts as read. - `contactIds: optional array of string` Array of contact IDs to mark as read. Only contacts with existing readReceipts will be updated. - `snoozedUntil: optional string` ISO datetime when the conversation should be unsnoozed. Required when state is "snoozed". Must be a future date. - `state: optional "open" or "closed" or "snoozed"` The state of the conversation. Use "snoozed" with snoozedUntil to snooze. - `"open"` - `"closed"` - `"snoozed"` - `teamAssigneeId: optional string` The team ID to assign the conversation to, or null to unassign. - `title: optional string` The title of the conversation. ### Returns - `Conversation object { id, adminAssigneeId, botConversationStateLastUpdatedAt, 26 more }` - `id: string` Unique conversation identifier - `adminAssigneeId: string` ID of the assigned admin - `botConversationStateLastUpdatedAt: string` ISO timestamp when bot state last changed - `brandId: string` ID of the brand associated with this conversation - `createdAt: string` ISO timestamp when conversation was created - `hasAdminOverriddenLanguage: boolean` Whether an admin has manually overridden the language for this conversation. When true, automatic language detection is disabled. - `isBlocked: boolean` Whether the user is blocked - `lastActivityAt: string` ISO timestamp of last activity - `object: "conversation"` Object type identifier - `"conversation"` - `participants: array of ConversationParticipant` Participants in this conversation - `id: string` Participant ID - `type: "customer" or "lead" or "admin" or 3 more` Type of participant - `"customer"` - `"lead"` - `"admin"` - `"bot"` - `"guest"` - `"integration"` - `priority: boolean` Whether this conversation is marked as priority - `prioritySetAt: string` ISO timestamp when priority was set - `snoozedUntil: string` ISO timestamp until which conversation is snoozed - `state: "open" or "closed" or "snoozed"` Current state of the conversation - `"open"` - `"closed"` - `"snoozed"` - `tags: array of ConversationTag` Current tags applied anywhere in this conversation - `id: string` Unique tag identifier - `name: string` Current tag name - `type: "tag"` Object type identifier for a tag - `"tag"` - `teamAssigneeId: string` ID of the assigned team - `updatedAt: string` ISO timestamp when conversation was last updated - `userPreferredLanguage: string` User's preferred language - `waitingSince: string` ISO timestamp when conversation started waiting - `awaitingCustomerReply: optional boolean` Whether we are awaiting a customer reply - `botConversationState: optional "active" or "handed_off_to_human" or "resolved"` State of AI agent handling for this conversation - `"active"` - `"handed_off_to_human"` - `"resolved"` - `conversationParts: optional array of ConversationPart` Array of conversation parts (messages). Only included when fetching a single conversation by ID. - `UserMsg object { id, bodyHtml, bodyMarkdown, 8 more }` Message from a customer or lead - `id: string` Unique part identifier - `bodyHtml: string` Message body content as HTML with signed image URLs - `bodyMarkdown: string` Message body content as markdown - `channel: "unknown" or "desktop" or "android" or 2 more` Channel through which the message was sent - `"unknown"` - `"desktop"` - `"android"` - `"ios"` - `"email"` - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "user_msg"` User message type - `"user_msg"` - `updatedAt: string` ISO timestamp when the part was last updated - `author: optional ConversationPartAuthor` - `id: string` Author ID - `type: "customer" or "lead" or "admin" or 3 more` Type of author - `"customer"` - `"lead"` - `"admin"` - `"bot"` - `"guest"` - `"integration"` - `email: optional string` Author email address - `name: optional string` Author display name - `profilePicture: optional string` Author profile picture URL - `redacted: optional boolean` Whether this message has been redacted - `tagApplications: optional array of ConversationTagApplication` Reply-level tag applications and provenance for this conversation part - `appliedAt: string` ISO timestamp when the tag was applied to this reply - `tagId: string` Identifier of the applied tag - `appliedBy: optional ConversationTagMutationActor` Actor that applied the tag - `type: "admin" or "customer" or "lead" or 4 more` Actor that caused the tag mutation - `"admin"` - `"customer"` - `"lead"` - `"bot"` - `"integration"` - `"system"` - `"workflow"` - `id: optional string` Actor identifier when available - `name: optional string` Actor display name when available - `removedAt: optional string` ISO timestamp when the tag was removed from this reply, if it was removed - `removedBy: optional ConversationTagMutationActor` Actor that applied the tag - `tag: optional ConversationTag` Resolved tag object when the tag still exists in the shared workspace catalog - `id: string` Unique tag identifier - `name: string` Current tag name - `type: "tag"` Object type identifier for a tag - `AdminMsg object { id, bodyHtml, bodyMarkdown, 8 more }` Message from an admin or support agent - `id: string` Unique part identifier - `bodyHtml: string` Message body content as HTML with signed image URLs - `bodyMarkdown: string` Message body content as markdown - `channel: "unknown" or "desktop" or "android" or 2 more` Channel through which the message was sent - `"unknown"` - `"desktop"` - `"android"` - `"ios"` - `"email"` - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "admin_msg"` Admin message type - `"admin_msg"` - `updatedAt: string` ISO timestamp when the part was last updated - `author: optional ConversationPartAuthor` - `redacted: optional boolean` Whether this message has been redacted - `tagApplications: optional array of ConversationTagApplication` Reply-level tag applications and provenance for this conversation part - `appliedAt: string` ISO timestamp when the tag was applied to this reply - `tagId: string` Identifier of the applied tag - `appliedBy: optional ConversationTagMutationActor` Actor that applied the tag - `removedAt: optional string` ISO timestamp when the tag was removed from this reply, if it was removed - `removedBy: optional ConversationTagMutationActor` Actor that applied the tag - `tag: optional ConversationTag` Resolved tag object when the tag still exists in the shared workspace catalog - `AdminNote object { id, bodyHtml, bodyMarkdown, 7 more }` Internal note visible only to admins - `id: string` Unique part identifier - `bodyHtml: string` Note body content as HTML with signed image URLs - `bodyMarkdown: string` Note body content as markdown - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "admin_note"` Admin internal note type - `"admin_note"` - `updatedAt: string` ISO timestamp when the part was last updated - `author: optional ConversationPartAuthor` - `redacted: optional boolean` Whether this message has been redacted - `tagApplications: optional array of ConversationTagApplication` Reply-level tag applications and provenance for this conversation part - `appliedAt: string` ISO timestamp when the tag was applied to this reply - `tagId: string` Identifier of the applied tag - `appliedBy: optional ConversationTagMutationActor` Actor that applied the tag - `removedAt: optional string` ISO timestamp when the tag was removed from this reply, if it was removed - `removedBy: optional ConversationTagMutationActor` Actor that applied the tag - `tag: optional ConversationTag` Resolved tag object when the tag still exists in the shared workspace catalog - `EmailMsg object { id, bodyHtml, bodyMarkdown, 8 more }` Message sent via email - `id: string` Unique part identifier - `bodyHtml: string` Email body content as HTML with signed image URLs - `bodyMarkdown: string` Email body content as markdown - `channel: "email"` Email channel - `"email"` - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "email_msg"` Email message type - `"email_msg"` - `updatedAt: string` ISO timestamp when the part was last updated - `author: optional ConversationPartAuthor` - `redacted: optional boolean` Whether this message has been redacted - `tagApplications: optional array of ConversationTagApplication` Reply-level tag applications and provenance for this conversation part - `appliedAt: string` ISO timestamp when the tag was applied to this reply - `tagId: string` Identifier of the applied tag - `appliedBy: optional ConversationTagMutationActor` Actor that applied the tag - `removedAt: optional string` ISO timestamp when the tag was removed from this reply, if it was removed - `removedBy: optional ConversationTagMutationActor` Actor that applied the tag - `tag: optional ConversationTag` Resolved tag object when the tag still exists in the shared workspace catalog - `BotMsg object { id, bodyHtml, bodyMarkdown, 8 more }` Automated message from AI or bot - `id: string` Unique part identifier - `bodyHtml: string` Bot message body content as HTML with signed image URLs - `bodyMarkdown: string` Bot message body content as markdown - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "bot_msg"` Bot message type - `"bot_msg"` - `updatedAt: string` ISO timestamp when the part was last updated - `author: optional ConversationPartAuthor` - `channel: optional "unknown" or "desktop" or "android" or 2 more` Channel through which the message was sent - `"unknown"` - `"desktop"` - `"android"` - `"ios"` - `"email"` - `redacted: optional boolean` Whether this message has been redacted - `tagApplications: optional array of ConversationTagApplication` Reply-level tag applications and provenance for this conversation part - `appliedAt: string` ISO timestamp when the tag was applied to this reply - `tagId: string` Identifier of the applied tag - `appliedBy: optional ConversationTagMutationActor` Actor that applied the tag - `removedAt: optional string` ISO timestamp when the tag was removed from this reply, if it was removed - `removedBy: optional ConversationTagMutationActor` Actor that applied the tag - `tag: optional ConversationTag` Resolved tag object when the tag still exists in the shared workspace catalog - `QuickReplyOpts object { id, createdAt, object, 6 more }` Presents options for user to choose from - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "quick_reply_opts"` Quick reply options type - `"quick_reply_opts"` - `replyOptions: array of object { id, text }` Available reply options - `id: string` Option ID - `text: string` Option text - `updatedAt: string` ISO timestamp when the part was last updated - `author: optional ConversationPartAuthor` - `redacted: optional boolean` Whether this message has been redacted - `tagApplications: optional array of ConversationTagApplication` Reply-level tag applications and provenance for this conversation part - `appliedAt: string` ISO timestamp when the tag was applied to this reply - `tagId: string` Identifier of the applied tag - `appliedBy: optional ConversationTagMutationActor` Actor that applied the tag - `removedAt: optional string` ISO timestamp when the tag was removed from this reply, if it was removed - `removedBy: optional ConversationTagMutationActor` Actor that applied the tag - `tag: optional ConversationTag` Resolved tag object when the tag still exists in the shared workspace catalog - `QuickReplyResp object { id, bodyHtml, bodyMarkdown, 8 more }` User's selection from quick reply options - `id: string` Unique part identifier - `bodyHtml: string` The selected option text as HTML - `bodyMarkdown: string` The selected option text as markdown - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "quick_reply_resp"` Quick reply response type - `"quick_reply_resp"` - `selectedOptionId: string` ID of the selected option - `updatedAt: string` ISO timestamp when the part was last updated - `author: optional ConversationPartAuthor` - `redacted: optional boolean` Whether this message has been redacted - `tagApplications: optional array of ConversationTagApplication` Reply-level tag applications and provenance for this conversation part - `appliedAt: string` ISO timestamp when the tag was applied to this reply - `tagId: string` Identifier of the applied tag - `appliedBy: optional ConversationTagMutationActor` Actor that applied the tag - `removedAt: optional string` ISO timestamp when the tag was removed from this reply, if it was removed - `removedBy: optional ConversationTagMutationActor` Actor that applied the tag - `tag: optional ConversationTag` Resolved tag object when the tag still exists in the shared workspace catalog - `RatingRequested object { id, createdAt, csat, 3 more }` Represents a persisted CSAT request in the conversation thread - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `csat: object { channel, requestedAt, requestId, 7 more }` Canonical CSAT request payload for this thread event - `channel: "desktop" or "email"` Channel used for the CSAT request - `"desktop"` - `"email"` - `requestedAt: string` ISO timestamp when the request was created - `requestId: string` Canonical CSAT request ID - `requestSource: "workflow"` Source that created the CSAT request - `"workflow"` - `status: "pending" or "rated" or "canceled" or "expired"` Status of the CSAT request represented by this part - `"pending"` - `"rated"` - `"canceled"` - `"expired"` - `changeLockWindowEndsAt: optional string` ISO timestamp after which changing the rating is no longer allowed - `expiredAt: optional string` ISO timestamp when the request expired, when applicable - `lateSubmitWindowEndsAt: optional string` ISO timestamp after which late submission is no longer allowed - `ratedAgent: optional CsatRatedAgent` - `type: "teammate" or "fibi" or "chatbot"` Type of agent the CSAT request is attributed to - `"teammate"` - `"fibi"` - `"chatbot"` - `id: optional string` Identifier of the rated agent when applicable - `workflow: optional CsatWorkflowLink` - `workflowActionId: optional string` Workflow action ID associated with the CSAT request - `workflowId: optional string` Workflow ID associated with the CSAT request - `workflowRunId: optional string` Workflow run ID associated with the CSAT request - `workflowStepId: optional string` Workflow step ID associated with the CSAT request - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "rating_requested"` CSAT rating requested part type - `"rating_requested"` - `updatedAt: string` ISO timestamp when the part was last updated - `RatingSubmitted object { id, createdAt, csat, 3 more }` Represents a persisted CSAT submission in the conversation thread - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `csat: object { channel, ratedAt, requestId, 7 more }` Canonical CSAT submission payload for this thread event - `channel: "desktop" or "email"` Channel used for the CSAT request - `"desktop"` - `"email"` - `ratedAt: string` ISO timestamp when the customer submitted the rating - `requestId: string` Canonical CSAT request ID - `requestSource: "workflow"` Source that created the CSAT request - `"workflow"` - `score: number` CSAT score from 1 to 5 - `status: "rated"` Submitted ratings are always in the rated state - `"rated"` - `ratedAgent: optional CsatRatedAgent` - `remark: optional string` Optional remark left with the rating - `requestedAt: optional string` ISO timestamp when the request was created - `workflow: optional CsatWorkflowLink` - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "rating_submitted"` CSAT rating submitted part type - `"rating_submitted"` - `updatedAt: string` ISO timestamp when the part was last updated - `AttrPrompt object { id, createdAt, form, 6 more }` Requests information from user via form - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `form: object { id, attributes }` Form configuration - `id: string` Form ID - `attributes: array of object { identifier, name, type }` Form fields - `identifier: string` Field identifier - `name: string` Field display name - `type: string` Field type - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "attr_prompt"` Attribute collection prompt type - `"attr_prompt"` - `updatedAt: string` ISO timestamp when the part was last updated - `author: optional ConversationPartAuthor` - `redacted: optional boolean` Whether this message has been redacted - `tagApplications: optional array of ConversationTagApplication` Reply-level tag applications and provenance for this conversation part - `appliedAt: string` ISO timestamp when the tag was applied to this reply - `tagId: string` Identifier of the applied tag - `appliedBy: optional ConversationTagMutationActor` Actor that applied the tag - `removedAt: optional string` ISO timestamp when the tag was removed from this reply, if it was removed - `removedBy: optional ConversationTagMutationActor` Actor that applied the tag - `tag: optional ConversationTag` Resolved tag object when the tag still exists in the shared workspace catalog - `AttrComplete object { id, createdAt, object, 2 more }` Indicates form was completed - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "attr_complete"` Attribute collection complete type - `"attr_complete"` - `updatedAt: string` ISO timestamp when the part was last updated - `Assign object { id, createdAt, object, 5 more }` Conversation assigned to admin or team - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "assign"` Assignment type - `"assign"` - `updatedAt: string` ISO timestamp when the part was last updated - `adminAssigneeId: optional string` ID of the admin assigned to the conversation - `adminAssignerId: optional string` ID of the admin who made the assignment - `teamAssigneeId: optional string` ID of the team assigned to the conversation - `Status object { id, createdAt, object, 4 more }` Conversation state changed (open/closed/snoozed) - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "status"` Status change type - `"status"` - `status: "open" or "closed" or "snoozed"` New conversation status - `"open"` - `"closed"` - `"snoozed"` - `updatedAt: string` ISO timestamp when the part was last updated - `snoozedUntil: optional string` ISO timestamp until conversation is snoozed (if snoozed) - `Tags object { id, action, createdAt, 8 more }` A tag was added to or removed from a specific reply - `id: string` Unique part identifier - `action: "added" or "removed"` Whether the tag was added or removed - `"added"` - `"removed"` - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `occurredAt: string` ISO timestamp when the tag mutation occurred - `partType: "tags"` Tag update type - `"tags"` - `tagId: string` Identifier of the affected tag - `updatedAt: string` ISO timestamp when the part was last updated - `actor: optional ConversationTagMutationActor` Actor that applied the tag - `tagName: optional string` Tag name at the time of the event or the best available current display name - `targetPartId: optional string` Conversation part that the tag mutation targeted - `WorkflowWait object { id, createdAt, object, 3 more }` Represents a workflow wait start, finish, or interruption in the conversation thread - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "workflow_wait"` Workflow wait event part type - `"workflow_wait"` - `updatedAt: string` ISO timestamp when the part was last updated - `workflowWait: object { eventType, occurredAt, interruptedByUserType, 3 more }` Workflow wait event payload for this thread event - `eventType: "started" or "finished" or "interrupted"` Lifecycle stage of the workflow wait event - `"started"` - `"finished"` - `"interrupted"` - `occurredAt: string` ISO timestamp when the wait event occurred - `interruptedByUserType: optional "admin" or "customer" or "lead"` User type that interrupted the wait when applicable - `"admin"` - `"customer"` - `"lead"` - `waitLabel: optional string` Human-readable wait duration or preset label - `workflowId: optional string` Workflow ID associated with the wait event - `workflowName: optional string` Workflow display name at the time of the wait event - `Priority object { id, createdAt, isPriority, 3 more }` Conversation priority was updated - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `isPriority: boolean` Whether the conversation is now marked as priority - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `partType: "priority"` Priority change type - `"priority"` - `updatedAt: string` ISO timestamp when the part was last updated - `PartAdd object { id, createdAt, object, 3 more }` New participant joined the conversation - `id: string` Unique part identifier - `createdAt: string` ISO timestamp when the part was created - `object: "conversation_part"` Object type identifier - `"conversation_part"` - `participant: object { id, type }` The added participant - `id: string` Participant ID - `type: "customer" or "lead" or "admin"` Participant type - `"customer"` - `"lead"` - `"admin"` - `partType: "part_add"` Participant added type - `"part_add"` - `updatedAt: string` ISO timestamp when the part was last updated - `csatDebug: optional object { requestId, status, changeLockWindowEndsAt, 2 more }` Minimal CSAT diagnostics for the current effective request. - `requestId: string` Canonical CSAT request ID used for the latest debug snapshot - `status: "pending" or "rated" or "canceled" or "expired"` Lifecycle status of the request represented in the debug snapshot - `"pending"` - `"rated"` - `"canceled"` - `"expired"` - `changeLockWindowEndsAt: optional string` ISO timestamp when rating edits stop being accepted - `emailDelivery: optional CsatEmailDelivery` - `status: "pending" or "sent" or "failed"` Email delivery status for the CSAT request when applicable - `"pending"` - `"sent"` - `"failed"` - `failedAt: optional string` ISO timestamp when the CSAT email failed - `failureReason: optional string` Operational failure reason for the CSAT email delivery - `messageId: optional string` Email message ID associated with delivery - `sentAt: optional string` ISO timestamp when the CSAT email was sent - `lateSubmitWindowEndsAt: optional string` ISO timestamp when first-time submissions stop being accepted - `csatHistory: optional array of object { channel, isLatestEffective, lastUpdatedAt, 14 more }` Historical CSAT requests for this conversation, ordered newest first. - `channel: "desktop" or "email"` Channel used for the CSAT request - `"desktop"` - `"email"` - `isLatestEffective: boolean` Whether this row represents the currently effective CSAT request for the conversation - `lastUpdatedAt: string` ISO timestamp when the request last changed - `requestedAt: string` ISO timestamp when the request was created - `requestId: string` Canonical CSAT request ID - `requestSource: "workflow"` Source that created the CSAT request - `"workflow"` - `status: "pending" or "rated" or "canceled" or "expired"` Lifecycle status for this historical CSAT request - `"pending"` - `"rated"` - `"canceled"` - `"expired"` - `canceledAt: optional string` ISO timestamp when the request was canceled - `changeLockWindowEndsAt: optional string` ISO timestamp when edits to an existing rating stop being accepted - `emailDelivery: optional CsatEmailDelivery` - `expiredAt: optional string` ISO timestamp when the request expired - `lateSubmitWindowEndsAt: optional string` ISO timestamp when first-time submissions stop being accepted - `ratedAgent: optional CsatRatedAgent` - `ratedAt: optional string` ISO timestamp when the request was rated - `remark: optional string` Submitted remark when present - `score: optional number` Submitted score when this request was rated - `workflow: optional CsatWorkflowLink` - `csatSummary: optional object { lastUpdatedAt, status, canceledAt, 10 more }` Derived CSAT summary for this conversation when a rating request or rating exists. - `lastUpdatedAt: string` ISO timestamp when the summary last changed - `status: "pending" or "rated" or "canceled" or "expired"` Current summary status for CSAT on this conversation - `"pending"` - `"rated"` - `"canceled"` - `"expired"` - `canceledAt: optional string` ISO timestamp when the request was canceled - `channel: optional "desktop" or "email"` Channel used for the latest CSAT request when known - `"desktop"` - `"email"` - `expiredAt: optional string` ISO timestamp when the request expired - `ratedAgent: optional CsatRatedAgent` - `ratedAt: optional string` ISO timestamp when the customer submitted a rating - `remark: optional string` Optional remark left with the rating - `requestedAt: optional string` ISO timestamp when the latest CSAT request was created - `requestId: optional string` Canonical CSAT request ID - `requestSource: optional "workflow"` Source of the latest CSAT request when known - `"workflow"` - `score: optional number` CSAT score from 1 to 5 when rated - `workflow: optional CsatWorkflowLink` - `disableCustomerReply: optional boolean` Whether customer replies are disabled - `readReceipts: optional array of object { id, lastReadPartId, userType }` Read receipts indicating how far each participant has read in the conversation. Each receipt maps a user to their last-read conversation part. The tracked position reflects the system read state and may reference parts the user cannot directly view (e.g., a contact's read position may point to an internal admin note). Use these receipts to render read indicators and typing awareness, not to infer content access. - `id: string` The internal ID of the user - `lastReadPartId: string` The ID of the last conversation part this user has read. Note: This reflects the system-tracked read position and may reference a part the user cannot directly access (e.g., internal notes for contacts). The read state is advanced to the latest part in the conversation regardless of part visibility. - `userType: "admin" or "customer" or "lead"` Type of user who has read the conversation - `"admin"` - `"customer"` - `"lead"` - `source: optional object { bodyHtml, bodyMarkdown, channel, 4 more }` - `bodyHtml: string` Body of the initial message as HTML with signed image URLs - `bodyMarkdown: string` Body of the initial message as markdown - `channel: "unknown" or "desktop" or "android" or 2 more` Channel through which the conversation was initiated - `"unknown"` - `"desktop"` - `"android"` - `"ios"` - `"email"` - `author: optional ConversationParticipant` - `id: string` Participant ID - `type: "customer" or "lead" or "admin" or 3 more` Type of participant - `deliveredAs: optional "customer_initiated" or "admin_initiated"` How the conversation was initiated - `"customer_initiated"` - `"admin_initiated"` - `subject: optional string` Subject line for email conversations - `url: optional string` URL where the conversation was initiated - `title: optional string` Conversation title ### Example ```http curl https://do.featurebase.app/v2/conversations/$ID \ -X PATCH \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $FEATUREBASE_API_KEY" \ -d '{ "actingAdminId": "507f1f77bcf86cd799439011", "adminAssigneeId": "507f1f77bcf86cd799439011", "customAttributes": { "priority_level": "bar", "category": "bar" }, "snoozedUntil": "2025-01-20T10:00:00.000Z", "state": "open", "teamAssigneeId": "507f1f77bcf86cd799439012", "title": "Question about pricing" }' ``` #### Response ```json { "id": "12345", "adminAssigneeId": "507f1f77bcf86cd799439011", "botConversationStateLastUpdatedAt": "2025-01-15T10:30:00.000Z", "brandId": "507f1f77bcf86cd799439011", "createdAt": "2025-01-15T10:30:00.000Z", "hasAdminOverriddenLanguage": false, "isBlocked": false, "lastActivityAt": "2025-01-15T12:30:00.000Z", "object": "conversation", "participants": [ { "id": "676f0f6765bdaa7d7d760f88", "type": "customer" } ], "priority": false, "prioritySetAt": "2025-01-15T10:30:00.000Z", "snoozedUntil": "2025-01-16T09:00:00.000Z", "state": "open", "tags": [ { "id": "67ec1234abcd5678ef901234", "name": "Churn", "type": "tag" } ], "teamAssigneeId": "507f1f77bcf86cd799439012", "updatedAt": "2025-01-15T12:30:00.000Z", "userPreferredLanguage": "en", "waitingSince": "2025-01-15T10:30:00.000Z", "awaitingCustomerReply": true, "botConversationState": "active", "conversationParts": [ { "id": "1", "bodyHtml": "
Hello, I have a question about your product.
", "bodyMarkdown": "Hello, I have a question about your product.", "channel": "desktop", "createdAt": "2025-01-15T10:30:00.000Z", "object": "conversation_part", "partType": "user_msg", "updatedAt": "2025-01-15T10:30:00.000Z", "author": { "id": "676f0f6765bdaa7d7d760f88", "type": "customer", "email": "john@example.com", "name": "John Doe", "profilePicture": "https://cdn.example.com/avatars/user.png" }, "redacted": false, "tagApplications": [ { "appliedAt": "2025-01-15T10:30:00.000Z", "tagId": "67ec1234abcd5678ef901234", "appliedBy": { "type": "admin", "id": "507f1f77bcf86cd799439011", "name": "John Doe" }, "removedAt": "2025-01-15T11:00:00.000Z", "removedBy": { "type": "admin", "id": "507f1f77bcf86cd799439011", "name": "John Doe" }, "tag": { "id": "67ec1234abcd5678ef901234", "name": "Churn", "type": "tag" } } ] } ], "csatDebug": { "requestId": "csat_req_123", "status": "pending", "changeLockWindowEndsAt": "2025-01-16T12:30:00.000Z", "emailDelivery": { "status": "failed", "failedAt": "2025-01-15T10:31:00.000Z", "failureReason": "smtp_bounce", "messageId": "msg_123", "sentAt": "2025-01-15T10:31:00.000Z" }, "lateSubmitWindowEndsAt": "2025-01-16T10:30:00.000Z" }, "csatHistory": [ { "channel": "desktop", "isLatestEffective": true, "lastUpdatedAt": "2025-01-15T10:35:00.000Z", "requestedAt": "2025-01-15T10:30:00.000Z", "requestId": "csat_req_123", "requestSource": "workflow", "status": "pending", "canceledAt": "2025-01-15T10:32:00.000Z", "changeLockWindowEndsAt": "2025-01-16T12:30:00.000Z", "emailDelivery": { "status": "failed", "failedAt": "2025-01-15T10:31:00.000Z", "failureReason": "smtp_bounce", "messageId": "msg_123", "sentAt": "2025-01-15T10:31:00.000Z" }, "expiredAt": "2025-01-16T10:30:00.000Z", "lateSubmitWindowEndsAt": "2025-01-16T10:30:00.000Z", "ratedAgent": { "type": "teammate", "id": "507f1f77bcf86cd799439011" }, "ratedAt": "2025-01-15T10:35:00.000Z", "remark": "Thanks for the quick help.", "score": 4, "workflow": { "workflowActionId": "action_123", "workflowId": "507f1f77bcf86cd799439011", "workflowRunId": "run_123", "workflowStepId": "step_123" } } ], "csatSummary": { "lastUpdatedAt": "2025-01-15T10:35:00.000Z", "status": "pending", "canceledAt": "2025-01-15T10:35:00.000Z", "channel": "desktop", "expiredAt": "2025-01-15T10:35:00.000Z", "ratedAgent": { "type": "teammate", "id": "507f1f77bcf86cd799439011" }, "ratedAt": "2025-01-15T10:35:00.000Z", "remark": "Very helpful support.", "requestedAt": "2025-01-15T10:30:00.000Z", "requestId": "csat_req_123", "requestSource": "workflow", "score": 5, "workflow": { "workflowActionId": "action_123", "workflowId": "507f1f77bcf86cd799439011", "workflowRunId": "run_123", "workflowStepId": "step_123" } }, "disableCustomerReply": false, "readReceipts": [ { "id": "507f1f77bcf86cd799439011", "lastReadPartId": "8", "userType": "admin" } ], "source": { "bodyHtml": "Hi, I have a question about your enterprise plan...
", "bodyMarkdown": "Hi, I have a question about your enterprise plan...", "channel": "desktop", "author": { "id": "676f0f6765bdaa7d7d760f88", "type": "customer" }, "deliveredAs": "customer_initiated", "subject": "Question about pricing", "url": "https://example.com/pricing" }, "title": "Question about pricing" } ```