Manage conversations and messages through the API

Create and manage conversations, read messages safely, and distinguish recorded API messages from channel delivery.

Updated

Use the public Platform API to record and manage workspace conversations from a trusted server. The base URL is https://api.protodesk.io/v1; internal /app endpoints are not the public integration contract. Verify your key's workspaceId and scopes with GET /v1/me first.

Create and find conversations

POST /v1/conversations requires an existing Protodesk customerId and a subject. It needs conversations:write. The default channel is api; omitted status and priority use the workspace's current defaults. The response contains the new conversation id, which is distinct from any optional externalId you supply. If you manage your own source objects, store that mapping and reconcile before retrying an uncertain creation.

POST /v1/conversations
Authorization: Bearer <server-held key>
Content-Type: application/json

{"customerId":"cus_example","subject":"Question about an order","channel":"api"}

The ID is illustrative, not a usable record. GET /v1/conversations requires conversations:read and supports filters including customerId, status, channel, and updated time. Use its nextCursor rather than assuming one page is complete. GET /v1/conversations/{conversationId} reads one record.

Manage state and ownership

Statuses and priorities are defined by each workspace. Read GET /v1/statuses and GET /v1/priorities before sending their keys; do not hard-code another workspace's labels. PATCH /v1/conversations/{conversationId} can update supported fields such as subject, status, priority, tags, team, or metadata. POST /v1/conversations/{conversationId}/assign changes assignee or team, and requires at least one of them. POST /v1/conversations/{conversationId}/resolve chooses the workspace's default completed-type status unless you supply another completed-type status key. These writes require conversations:write; an invalid workspace status or assignee can fail validation.

Read and record messages

GET /v1/conversations/{conversationId}/messages requires conversations:read. Messages are listed chronologically with pagination. Use visibility=public when building a customer-facing view, so internal notes are excluded; the default all includes internal messages and must not be exposed to customers.

POST /v1/conversations/{conversationId}/messages requires messages:write and a nonempty body or attachment. sender can be customer, agent, ai, or system and defaults to customer; channel defaults to api. internal: true marks a message as an internal note. Use the correct sender and visibility for your source data. A unique externalId can help reconcile imported messages; a duplicate returns a conflict.

Recording is not delivery. This public POST stores a message and emits a workspace event. It does not, by itself, dispatch an email, WhatsApp message, or Chat reply to the customer. A 201 means the record was created, not that a person received it. Do not use this route as an outbound-channel send API or promise scheduled delivery from sendAt or clientId; those fields are not processed by this public handler. Use a separately documented, supported channel-sending workflow for delivery.

For exact request schemas, scopes, response codes, and endpoint-specific Idempotency-Key support, consult the public OpenAPI contract and API reliability guide. Never expose a workspace API key or an unfiltered internal-message feed in a customer client.

Related articles