# Create a conversation Creates a new conversation. Supports both contact-initiated (customer/lead) and admin-initiated (outreach) conversations. ## Contact-Initiated Conversation For conversations started by a customer or lead: | Field | Type | Required | Description | |-------|------|----------|-------------| | from.type | string | Yes | Must be "contact" | | from.id | string | Yes | The Featurebase contact ID (24-character ObjectId) | | bodyMarkdown | string | Yes | The initial message content in markdown format. Images referenced by URL or as base64 data URIs will be automatically uploaded and stored. | | channel | string | No | The channel: "desktop" (default) or "email" | | createdAt | string | No | ISO timestamp for migrations | ### Example Contact-Initiated Request json { "from": { "type": "contact", "id": "676f0f6765bdaa7d7d760f88" }, "bodyMarkdown": "Hello, I have a question about your product.", "channel": "desktop" } ## Admin-Initiated Outreach For outreach conversations started by an admin: | Field | Type | Required | Description | |-------|------|----------|-------------| | from.type | string | Yes | Must be "admin" | | from.id | string | Yes | The Featurebase admin ID (24-character ObjectId) | | bodyMarkdown | string | Yes | The initial message content in markdown format. Images referenced by URL or as base64 data URIs will be automatically uploaded and stored. | | channel | string | No | The channel: "desktop" (default) or "email" | | recipients | object | Yes | Recipients for the outreach | | recipients.to | object | Yes | Primary recipients | | recipients.to.emails | string[] | No* | Email addresses | | recipients.to.ids | string[] | No* | Featurebase contact IDs | | recipients.cc | object | No | CC recipients (same structure as "to") | | recipients.bcc | object | No | BCC recipients (same structure as "to") | | subject | string | No | Email subject line | | createdAt | string | No | ISO timestamp for migrations | *At least one email or ID is required in recipients.to Required when channel is "email" ### Example Admin Outreach (In-App) json { "from": { "type": "admin", "id": "507f1f77bcf86cd799439011" }, "bodyMarkdown": "Hi! Just following up on your inquiry.", "channel": "desktop", "recipients": { "to": { "ids": ["676f0f6765bdaa7d7d760f88"] } } } ### Example Admin Outreach (Email) json { "from": { "type": "admin", "id": "507f1f77bcf86cd799439011" }, "bodyMarkdown": "Hi! Just following up on your inquiry.", "channel": "email", "subject": "Following up on your inquiry", "recipients": { "to": { "emails": ["john@example.com"] }, "cc": { "emails": ["manager@example.com"] } } } ### Response Returns the created conversation object with a 201 Created status. ### Example Response json { "object": "conversation", "id": "12345", "state": "open", "priority": false, "adminAssigneeId": null, "participants": [ { "type": "customer", "id": "676f0f6765bdaa7d7d760f88" } ], "source": { "channel": "desktop", "deliveredAs": "customer_initiated", "bodyHtml": "Hello, I have a question about your product.", "bodyMarkdown": "Hello, I have a question about your product.", "author": { "type": "customer", "id": "676f0f6765bdaa7d7d760f88" } }, "createdAt": "2025-01-15T10:30:00.000Z", "updatedAt": "2025-01-15T10:30:00.000Z" } ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. Endpoint: POST /v2/conversations 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" ## Request fields (application/json): - `from` (any, required) The author initiating the conversation. Use type "contact" for customer/lead or "admin" for outreach. - `bodyMarkdown` (string, required) The content of the initial message in markdown format. Images referenced by URL or as base64 data URIs will be automatically uploaded and stored. Example: "Hello, I have a question about your product.\n\n" - `channel` (string) The channel for the conversation. Defaults to "desktop" (SDK/widget). Enum: "desktop", "email" - `recipients` (object) Recipients for admin-initiated outreach. Required when from.type is "admin". Specify at least one recipient in the "to" field. - `recipients.to` (object, required) Primary recipients (To field) - `recipients.to.emails` (array) Array of email addresses Example: ["john@example.com"] - `recipients.to.ids` (array) Array of Featurebase contact IDs Example: ["676f0f6765bdaa7d7d760f88"] - `recipients.cc` (object) Primary recipients (To field) - `recipients.bcc` (object) Primary recipients (To field) - `subject` (string) Subject line for the email. Required when channel is "email" and from.type is "admin". Example: "Following up on your inquiry" - `createdAt` (string,null) The time the conversation was created as an ISO timestamp. If not provided, the current time will be used. This field is recommended for migrating past conversations from another source. Example: "2025-01-15T10:30:00.000Z" ## Response 201 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 400 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: "invalid_content", "missing_parameter", "invalid_parameter", null - `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: 400 ## 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: "contact_not_found", "admin_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