# Add a contact to a conversation Adds a contact (customer or lead) as a participant to an existing conversation. ### Path Parameters - id - The conversation ID (short ID) ### Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | participant | object | Yes | The contact to add (see below) | | participant.id | string | No* | The Featurebase ID (24-character ObjectId) - matches customer or lead | | participant.userId | string | No* | External user ID from your system - matches customer only | | participant.email | string | No* | Email address - matches customer only | | actingAdminId | string | No | Admin ID performing the action (for attribution) | *At least one of id, userId, or email is required in the participant object. ### Lookup Priority 1. If id is provided, looks up by Featurebase ID (matches both customer and lead types) 2. If userId is provided, looks up by external user ID (matches customer type only) 3. If email is provided, looks up by email address (matches customer type only) ### Response Returns the updated conversation object. ### Example Request (by Featurebase ID) json { "participant": { "id": "676f0f6765bdaa7d7d760f88" }, "actingAdminId": "507f1f77bcf86cd799439011" } ### Example Request (by external userId) json { "participant": { "userId": "user_123" } } ### Example Request (by email) json { "participant": { "email": "john@example.com" } } ### Example Response json { "object": "conversation", "id": "12345", "participants": [ { "type": "customer", "id": "676f0f6765bdaa7d7d760f88" }, { "type": "customer", "id": "676f0f6765bdaa7d7d760f89" } ], ... } ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. Endpoint: POST /v2/conversations/{id}/participants Version: 2026-01-01.nova Security: bearerAuth ## Header parameters: - `Featurebase-Version` (string) API version for this request. Defaults to your organization's configured API version if not specified. Example: "2026-01-01.nova" ## Path parameters: - `id` (string, required) Conversation ID (short ID) Example: "12345" ## Request fields (application/json): - `participant` (object, required) The contact to add as a participant. At least one of id, userId, or email is required. - `participant.id` (string) The Featurebase ID of the contact (customer or lead) Example: "676f0f6765bdaa7d7d760f88" - `participant.userId` (string) The external user ID from your system (matches customer type only) Example: "user_123" - `participant.email` (string) The email address of the contact (matches customer type only) Example: "john@example.com" - `actingAdminId` (string) The admin ID performing this action. If not provided, changes are attributed to the system bot user. Example: "507f1f77bcf86cd799439011" ## Response 200 fields (application/json): - `object` (string, required) Object type identifier Enum: "conversation" - `id` (string, required) Unique conversation identifier Example: "12345" - `title` (string) Conversation title Example: "Question about pricing" - `state` (string, required) Current state of the conversation Enum: "open", "closed", "snoozed" - `isBlocked` (boolean, required) Whether the user is blocked - `priority` (boolean, required) Whether this conversation is marked as priority - `prioritySetAt` (string,null, required) ISO timestamp when priority was set Example: "2025-01-15T10:30:00.000Z" - `adminAssigneeId` (string,null, required) ID of the assigned admin Example: "507f1f77bcf86cd799439011" - `teamAssigneeId` (string,null, required) ID of the assigned team Example: "507f1f77bcf86cd799439012" - `userPreferredLanguage` (string, required) User's preferred language Example: "en" - `source` (object) - `source.channel` (string, required) Channel through which the conversation was initiated Enum: "unknown", "desktop", "android", "ios", "email" - `source.deliveredAs` (string) How the conversation was initiated Enum: "customer_initiated", "admin_initiated" - `source.subject` (string) Subject line for email conversations Example: "Question about pricing" - `source.bodyHtml` (string, required) Body of the initial message as HTML with signed image URLs Example: "
Hi, I have a question about your enterprise plan...
" - `source.bodyMarkdown` (string, required) Body of the initial message as markdown Example: "Hi, I have a question about your enterprise plan..." - `source.author` (object) - `source.author.type` (string, required) Type of participant Enum: "customer", "lead", "admin", "bot", "guest", "integration" - `source.author.id` (string, required) Participant ID Example: "676f0f6765bdaa7d7d760f88" - `source.url` (string) URL where the conversation was initiated Example: "https://example.com/pricing" - `participants` (array, required) Participants in this conversation - `botConversationState` (string) State of AI agent handling for this conversation Enum: "active", "handed_off_to_human", "resolved" - `botConversationStateLastUpdatedAt` (string,null, required) ISO timestamp when bot state last changed Example: "2025-01-15T10:30:00.000Z" - `disableCustomerReply` (boolean) Whether customer replies are disabled - `awaitingCustomerReply` (boolean) Whether we are awaiting a customer reply Example: true - `lastActivityAt` (string,null, required) ISO timestamp of last activity Example: "2025-01-15T12:30:00.000Z" - `waitingSince` (string,null, required) ISO timestamp when conversation started waiting Example: "2025-01-15T10:30:00.000Z" - `snoozedUntil` (string,null, required) ISO timestamp until which conversation is snoozed Example: "2025-01-16T09:00:00.000Z" - `createdAt` (string, required) ISO timestamp when conversation was created Example: "2025-01-15T10:30:00.000Z" - `updatedAt` (string, required) ISO timestamp when conversation was last updated Example: "2025-01-15T12:30:00.000Z" - `readReceipts` (array) 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. - `readReceipts.id` (string, required) The internal ID of the user Example: "507f1f77bcf86cd799439011" - `readReceipts.userType` (string, required) Type of user who has read the conversation Enum: "admin", "customer", "lead" - `readReceipts.lastReadPartId` (string, required) 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. Example: "8" - `conversationParts` (array) Array of conversation parts (messages). Only included when fetching a single conversation by ID. ## Response 403 fields (application/json): - `error` (object, required) - `error.type` (string, required) The type of error returned Enum: "authorization_error" - `error.code` (string, required) Machine-readable error code Enum: "forbidden" - `error.message` (string, required) Human-readable error message Example: "An error occurred" - `error.param` (string) The parameter that caused the error (if applicable) Example: "id" - `error.status` (number, required) HTTP status code Enum: 403 ## Response 404 fields (application/json): - `error` (object, required) - `error.type` (string, required) The type of error returned Enum: "invalid_request_error" - `error.code` (string, required) Machine-readable error code Enum: "conversation_not_found", "contact_not_found" - `error.message` (string, required) Human-readable error message Example: "An error occurred" - `error.param` (string) The parameter that caused the error (if applicable) Example: "id" - `error.status` (number, required) HTTP status code Enum: 404