Skip to content

Support API

REST endpoints for the Support area of Lessly.

The Support area publishes 44 REST endpoints. Paths are relative to https://api.lessly.com; see Authentication for the required header.

GET/support/agents

List this product support agents by display name. Deactivated agents are hidden unless asked for: they keep every message they wrote but cannot take new threads. Through the public edge the profiles come back without lesslyUserId — the binding never leaves the authenticated plane

MCP tool: support_agent_list

Parameters

NameInTypeRequiredDescription
includeInactivequerybooleanAlso return deactivated agents (default false)

Response

Returns object.

FieldTypeAlwaysDescription
agentsobject[]The product support agents, by display name
POST/support/agents

Create a support agent profile for this product. Binding a Lessly identity is optional and the value is stored verbatim — nothing resolves it or checks that the user exists. An unbound profile is a bot or the client's own backend, and it replies exactly like a human agent does

MCP tool: support_agent_create

Parameters

NameInTypeRequiredDescription
displayNamebodystringName the end user sees next to this agent replies
titlebodystringJob title shown under the name, e.g. "Support engineer"
avatarUrlbodystring (uri)Absolute URL of the agent avatar image
lesslyUserIdbodystringLessly identity to bind this profile to, stored verbatim as an opaque string. It is never resolved, validated against the platform or enriched. Omit it for a bot or a backend profile. At most one agent per product may claim a given Lessly user

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Agent id
titlestring | nullJob title shown under the name, or null if unset
isActivebooleanA deactivated agent keeps its history but can no longer be put on a thread
avatarUrlstring | nullAvatar image URL, or null if unset
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-modification timestamp
displayNamestringName shown next to the agent replies
lesslyUserIdstring | nullBound Lessly identity, stored verbatim and resolved by nobody. Null for an unbound profile — a bot or the client's own backend, which replies just like anyone else
GET/support/agents/:id

Get one support agent by id, deactivated ones included. An agent belonging to another product is reported as not found. Through the public edge the profile comes back without lesslyUserId — the binding never leaves the authenticated plane

MCP tool: support_agent_get

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Agent id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Agent id
titlestring | nullJob title shown under the name, or null if unset
isActivebooleanA deactivated agent keeps its history but can no longer be put on a thread
avatarUrlstring | nullAvatar image URL, or null if unset
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-modification timestamp
displayNamestringName shown next to the agent replies
lesslyUserIdstring | nullBound Lessly identity, stored verbatim and resolved by nobody. Null for an unbound profile — a bot or the client's own backend, which replies just like anyone else
PATCH/support/agents/:id

Edit an agent profile. Pass null to clear the title, the avatar or the Lessly binding; omit a field to leave it alone. Setting isActive to false deactivates the agent: it keeps every message it wrote and every thread it already sits on, but cannot be assigned to another one

MCP tool: support_agent_update

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Agent id
displayNamebodystringName the end user sees next to this agent replies
titlebodystring | nullNew job title, or null to clear it
avatarUrlbodystring (uri) | nullNew avatar URL, or null to clear it
lesslyUserIdbodystring | nullLessly identity to bind, or null to unbind. Stored verbatim, resolved by nobody
isActivebodybooleanDeactivate or reactivate. A deactivated agent keeps every message it wrote and every thread it already sits on, but cannot be assigned to another one

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Agent id
titlestring | nullJob title shown under the name, or null if unset
isActivebooleanA deactivated agent keeps its history but can no longer be put on a thread
avatarUrlstring | nullAvatar image URL, or null if unset
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-modification timestamp
displayNamestringName shown next to the agent replies
lesslyUserIdstring | nullBound Lessly identity, stored verbatim and resolved by nobody. Null for an unbound profile — a bot or the client's own backend, which replies just like anyone else
POST/support/attachments

Reserve a file on a support thread and get a short-lived signed URL to upload it to. The bytes never pass through this API: PUT them to the returned uploadUrl with the same Content-Type AND the header "x-goog-content-length-range: 0,26214400", both of which the signature covers — omit either and storage refuses the PUT. Then call support_attachment_finalize, which checks that the first bytes really are the type you declared. Only the content types listed on the contentType field are accepted. A thread may hold at most 20 attachments waiting for their bytes at once; past that the call is refused with 429 and a message beginning "too_many_pending_attachments". Until finalized the attachment is pending — it cannot be attached to a message and is invisible in message output. A thread belonging to another product is reported as not found

MCP tool: support_attachment_create

Parameters

NameInTypeRequiredDescription
threadIdbodystring (uuid)Thread the file belongs to. An attachment is created against a thread first and claimed by one of its messages later, when that message is posted
fileNamebodystringDisplay name of the file, e.g. "invoice.pdf". Only the base name is used for the storage key; any directory part is discarded
contentTypebodystringone of: image/jpeg, image/png, image/gif, image/webp, image/heic, video/mp4, video/webm, video/quicktime, application/pdf, text/plain, application/zipMIME type of the file, which must be one of: image/jpeg, image/png, image/gif, image/webp, image/heic, video/mp4, video/webm, video/quicktime, application/pdf, text/plain, application/zip. Exact strings only — a parameter such as "; charset=utf-8" is refused. The upload URL is signed for exactly this type, so the PUT must send the same Content-Type header, and finalize refuses the file unless its first bytes really are this type
sizeBytesbodyintegerSize of the file in bytes, at most 26214400. Declared up front so an oversized upload is refused before a URL is issued; finalize checks the real size again

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Attachment id
statusstringone of: pending, uploaded, rejectedpending: the row exists and an upload URL was issued, but no bytes have been confirmed. uploaded: finalize saw the object in storage and its first bytes matched the declared type. rejected: they did not, the object was deleted, and this attachment is finished — the state is terminal. Only uploaded attachments can be attached to a message or downloaded
fileNamestringDisplay name of the file
threadIdstring (uuid)Thread this attachment belongs to
createdAtstringISO-8601 creation timestamp
messageIdstring (uuid) | nullThe message that carries this attachment, or null while nothing claims it yet
sizeBytesintegerSize in bytes: what the caller declared while the attachment is pending, what storage reported once it is uploaded
uploadUrlstringShort-lived signed URL. PUT the file bytes here with the same Content-Type, then call support_attachment_finalize. The URL is a bearer credential for this one object
uploadedAtstring | nullISO-8601 timestamp of the confirmed upload, or null while pending
contentTypestringMIME type declared when the attachment was created
rejectedReasonstring | nullWhy finalize refused the file — signature_mismatch, not_utf8, nul_byte or markup_in_text — or null in any state but rejected
uploadExpiresAtstringISO-8601 moment the upload URL stops working
POST/support/attachments/finalize

Confirm that an upload landed. Storage is asked whether the object exists and how large it is; if it is not there the call is refused and the attachment stays pending. Its first 4 KiB are then read and checked against the content type the attachment was created with: if the bytes are something else — an svg uploaded as a png, html uploaded as text — the object is DELETED, the attachment becomes rejected, and the call answers 400 with a message beginning "attachment_rejected" and naming the reason. That state is terminal: calling finalize again returns the same 400, and the file must be created and uploaded afresh. On success the attachment becomes uploaded — it can now be named in support_message_create and carries a download URL served under the verified type. Calling it again on an uploaded attachment is safe and simply returns a fresh download URL

MCP tool: support_attachment_finalize

Parameters

NameInTypeRequiredDescription
attachmentIdbodystring (uuid)The attachment whose upload should be confirmed, as returned by the create call

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Attachment id
statusstringone of: pending, uploaded, rejectedpending: the row exists and an upload URL was issued, but no bytes have been confirmed. uploaded: finalize saw the object in storage and its first bytes matched the declared type. rejected: they did not, the object was deleted, and this attachment is finished — the state is terminal. Only uploaded attachments can be attached to a message or downloaded
fileNamestringDisplay name of the file
threadIdstring (uuid)Thread this attachment belongs to
createdAtstringISO-8601 creation timestamp
messageIdstring (uuid) | nullThe message that carries this attachment, or null while nothing claims it yet
sizeBytesintegerSize in bytes: what the caller declared while the attachment is pending, what storage reported once it is uploaded
uploadedAtstring | nullISO-8601 timestamp of the confirmed upload, or null while pending
contentTypestringMIME type declared when the attachment was created
downloadUrlstringShort-lived signed URL to read the uploaded file
rejectedReasonstring | nullWhy finalize refused the file — signature_mismatch, not_utf8, nul_byte or markup_in_text — or null in any state but rejected
GET/support/labels

List this product label dictionary by name. A product that has invented no tags yet gets an empty list — unlike statuses, there is nothing to seed

MCP tool: support_label_list

Parameters

No parameters.

Response

Returns object.

FieldTypeAlwaysDescription
labelsobject[]The product label dictionary, by name
POST/support/labels

Add a label to this product label dictionary. A label is a free-form tag: nothing automates off it and a thread may carry any number of them. Names are unique per product

MCP tool: support_label_create

Parameters

NameInTypeRequiredDescription
namebodystringLabel name as the customer wants to see it. Unique within the product
colorbodystringOptional display colour as a six-digit hex string, e.g. #2563eb

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Label id
namestringLabel name, unique within the product
colorstring | nullDisplay colour as a hex string, or null if uncoloured
createdAtstringISO-8601 creation timestamp
GET/support/messages

List messages oldest first — the conversation reads forward. Name a threadId to read one thread, or omit it to read every thread of this product, which is how a client catches up on what it missed: pass since with the timestamp of the last message it has, then follow nextCursor until it comes back null. Paging is stable across messages that share a timestamp, so a walk neither skips nor repeats one. Filter by direction and by visibility; omit visibility to get public messages and internal notes together. A thread belonging to another product is reported as not found

MCP tool: support_message_list

Parameters

NameInTypeRequiredDescription
threadIdquerystring (uuid)Thread whose messages to list. Omit to list the messages of every thread of this product — the catch-up read
directionquerystringone of: inbound, outboundOnly messages in this direction
visibilityquerystringone of: public, internalOnly messages with this visibility. Omit to get both public and internal
sincequerystring (date-time)ISO-8601 timestamp. Only messages created strictly after it — pass the createdAt of the last message you already have
cursorquerystringOpaque position from a previous nextCursor. Resumes exactly where that page ended, with no gap and no repeat even when messages share a timestamp. Never construct one, and do not combine it with offset
limitqueryintegerPage size, 1..100 (default 50)
offsetqueryintegerNumber of messages to skip. The older pagination, kept for callers that already use it; prefer cursor, which cannot drift as messages arrive

Response

Returns object.

FieldTypeAlwaysDescription
limitintegerPage size that was applied
offsetintegerOffset that was applied
messagesobject[]The requested page of messages, oldest first — the conversation reads forward
nextCursorstring | nullPosition to resume from: pass it back as cursor for the next page. Null when this page is the last one
POST/support/messages

Post a message into a support thread. A message has exactly one author: either an opaque external identifier from the client's own user base, or a support agent — never both and never neither. Direction, authorship and visibility are independent: an internal note may be inbound or outbound. Posting a message moves the parent thread's last reply timestamp. A message may carry files: create and finalize them first, then name them in attachmentIds. Through the public edge an agent author is accepted only if that agent carries no Lessly binding — a bot or the calling backend; an agent bound to a Lessly identity may author only from a signed-in session

MCP tool: support_message_create

Parameters

NameInTypeRequiredDescription
threadIdbodystring (uuid)Id of the thread this message belongs to
bodybodystringThe message text, stored verbatim
directionbodystringone of: inbound, outboundinbound: written by the external end user. outbound: written by support, going out to them
authorExternalIdbodystringOpaque identifier of the external end user in the client's own user base, stored verbatim. Set this exactly when the message comes from outside; leave authorAgentId empty
authorAgentIdbodystring (uuid)The support agent of this product who wrote the message. Set this exactly when the message comes from inside the support contour; leave authorExternalId empty. An agent of another product is reported as not found
visibilitybodystringone of: public, internalDefaults to public when omitted. Internal notes are never shown to the end user
attachmentIdsbodystring (uuid)[]Files this message carries, created with support_attachment_create and confirmed with support_attachment_finalize beforehand. Each must be an uploaded attachment of the same thread that no other message already carries; otherwise the whole message is refused. At most 10 per message

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Message id
bodystringThe message text, byte-identical to what was stored
threadIdstring (uuid)Thread this message belongs to
createdAtstringISO-8601 creation timestamp
directionstringone of: inbound, outboundinbound: written by the external end user. outbound: written by support, going out to them
visibilitystringone of: public, internalpublic: part of the conversation the external end user sees. internal: a note between agents that never leaves the support contour
attachmentsobject[]Files this message carries, each with a freshly signed download URL. Empty when there are none. Attachments whose upload was never confirmed are never listed here
authorAgentIdstring (uuid) | nullThe agent author, or null when the external end user wrote the message
authorExternalIdstring | nullThe external author, or null when an agent wrote the message
GET/support/responses

List the responses of ONE survey, newest first — surveyId is required, because a page mixing two surveys would carry answers keyed by two different question sets. Filters: score range (scoreMin/scoreMax, inclusive — a response with no score matches neither bound), a creation window (from/to), completed, plus pagination

MCP tool: support_response_list

Parameters

NameInTypeRequiredDescription
surveyIdquerystring (uuid)Required: responses are always read one survey at a time
scoreMinqueryintegerOnly responses scored at or above this value (inclusive). A response with no score matches neither bound — not even at the bottom of the scale
scoreMaxqueryintegerOnly responses scored at or below this value (inclusive). A response with no score matches neither bound — not even at the bottom of the scale
fromquerystring (date-time)Only responses created at or after this ISO-8601 timestamp
toquerystring (date-time)Only responses created at or before this ISO-8601 timestamp
completedqueryboolean | stringone of: true, falsetrue: only responses that reached the end. false: only partial ones
limitqueryintegerPage size, 1..100 (default 25)
offsetqueryintegerNumber of responses to skip

Response

Returns object.

FieldTypeAlwaysDescription
limitintegerPage size that was applied
offsetintegerOffset that was applied
responsesobject[]The requested page of responses, newest first
GET/support/responses/:id

Get one survey response by id, with its answers exactly as they were submitted. A response belonging to another product is reported as not found

MCP tool: support_response_get

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Response id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Response id
scoreinteger | nullThe answer of the first nps or rating question, raw and never rescaled, or null when neither was answered. Null is not zero — 0 is a real score at the bottom of an NPS scale
answersobjectAnswers keyed by question id, exactly as stored
metadataobjectFree-form client-owned JSON
surveyIdstring (uuid)The survey that was answered
completedbooleanWhether the respondent reached the end
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-modification timestamp
authorExternalIdstringThe respondent, byte-identical to what was stored
escalatedThreadIdstring (uuid) | nullThe feedback thread this response was escalated into, or null while it has not been
POST/support/responses/:id/escalate

Turn a survey response into a feedback thread so a person can follow up. The thread opens on the product’s default open status, titled with the survey’s name, authored by the same external respondent, carrying the response metadata plus surveyResponseId, and rated with the response score when it fits 0..10. No message is written — the answers stay on the response, and neither the end user nor an agent typed anything. A response that was already escalated is refused with a conflict naming the thread it went to

MCP tool: support_response_escalate

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Response id

Response

Returns object.

FieldTypeAlwaysDescription
threadobjectThe feedback thread that was opened
responseobjectThe response, with escalatedThreadId now set
GET/support/rules

List this product’s delivery rules, newest first, optionally narrowed to one survey, to the live or switched-off ones, or to the rules that apply to a given page URL and device. This is the same answer a client’s runtime fetches through the public edge, where a URL is required and only live rules on published surveys are visible

MCP tool: support_rule_list

Parameters

NameInTypeRequiredDescription
surveyIdquerystring (uuid)Only rules delivering this survey
enabledqueryboolean | stringone of: true, falsetrue: only live rules. false: only switched-off ones
urlquerystringOnly rules whose URL match applies to this page URL
devicequerystringone of: desktop, mobileThe device the page is rendered on. Without it only rules targeting any device match
limitqueryintegerPage size, 1..100 (default 25)
offsetqueryintegerNumber of rules to skip

Response

Returns object.

FieldTypeAlwaysDescription
limitintegerPage size that was applied
rulesobject[]The requested page of rules, newest first
offsetintegerOffset that was applied
POST/support/rules

Write a delivery rule: where a survey should be shown (a URL match), on which devices, when (immediately, after a delay, or on the client’s own event) and how often. Nothing here runs on this side — the rule is configuration a client’s own runtime reads back through the public edge and acts on. A rule reaches that edge only while its survey is published, so a rule may be written against a draft and simply waits

MCP tool: support_rule_create

Parameters

NameInTypeRequiredDescription
surveyIdbodystring (uuid)The survey this rule delivers. It must belong to this product
urlMatchbodyobjectWhich pages this rule applies to
triggerbodyobjectWhen to show the survey once the page matches
frequencybodyobjectHow often the same person may see this survey
devicebodystringone of: any, desktop, mobileWhich devices this rule applies to (default any)
enabledbodybooleanWhether the rule is live. A rule is created enabled unless this says otherwise
attributeConditionsbodyobject[]Conditions on the visitor’s attributes. Omit for a rule that applies to everyone

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Rule id
devicestringone of: any, desktop, mobileWhich devices the rule applies to. any is the rule that does not care and is the default
enabledbooleanWhether the rule is live
triggerobject
surveyIdstring (uuid)The survey this rule delivers
urlMatchobjectWhich pages match
createdAtstringISO-8601 creation timestamp
frequencyobject
updatedAtstringISO-8601 last-modification timestamp
attributeConditionsobject[]Conditions on the visitor’s attributes, ALL of which must hold
DELETE/support/rules/:id

Delete a delivery rule for good. Unlike a survey, a rule is not archived — it has no responses behind it and nothing outlives it, so the row is removed and cannot be recovered. The survey it targeted is untouched. To stop delivery reversibly, set enabled to false instead

MCP tool: support_rule_delete

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Rule id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Id of the rule that was deleted
deletedbooleanone of: trueAlways true — the rule is gone
GET/support/rules/:id

Get one delivery rule by id, with its whole configuration. A rule belonging to another product is reported as not found

MCP tool: support_rule_get

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Rule id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Rule id
devicestringone of: any, desktop, mobileWhich devices the rule applies to. any is the rule that does not care and is the default
enabledbooleanWhether the rule is live
triggerobject
surveyIdstring (uuid)The survey this rule delivers
urlMatchobjectWhich pages match
createdAtstringISO-8601 creation timestamp
frequencyobject
updatedAtstringISO-8601 last-modification timestamp
attributeConditionsobject[]Conditions on the visitor’s attributes, ALL of which must hold
PATCH/support/rules/:id

Edit a delivery rule: its URL match, device, trigger, frequency, conditions, or whether it is live at all. Every value replaces the old one whole rather than merging into it. The survey is not editable — a rule is the targeting OF one survey, and retargeting it silently would change what every matching page shows; delete it and write the one you meant. Switching a rule off is the quiet way to stop delivering without touching the survey

MCP tool: support_rule_update

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Rule id
urlMatchbodyobjectThe new URL match, replacing the old one
triggerbodyobjectThe new trigger, replacing the old one
frequencybodyobjectThe new frequency, replacing the old one
devicebodystringone of: any, desktop, mobileThe new device targeting
enabledbodybooleanTurn the rule on or off
attributeConditionsbodyobject[]The complete new condition set, replacing the old one. Pass [] to clear it

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Rule id
devicestringone of: any, desktop, mobileWhich devices the rule applies to. any is the rule that does not care and is the default
enabledbooleanWhether the rule is live
triggerobject
surveyIdstring (uuid)The survey this rule delivers
urlMatchobjectWhich pages match
createdAtstringISO-8601 creation timestamp
frequencyobject
updatedAtstringISO-8601 last-modification timestamp
attributeConditionsobject[]Conditions on the visitor’s attributes, ALL of which must hold
GET/support/statuses

List this product status dictionary in display order. A product that never opened settings gets the four defaults seeded on the first call. Archived statuses are hidden unless asked for

MCP tool: support_status_list

Parameters

NameInTypeRequiredDescription
includeArchivedquerybooleanAlso return archived statuses (default false)

Response

Returns object.

FieldTypeAlwaysDescription
statusesobject[]The product status dictionary, in display order
POST/support/statuses

Add a status to this product status dictionary. The name is what people see; the category is what automation and reporting read, and it cannot change once threads sit on the status

MCP tool: support_status_create

Parameters

NameInTypeRequiredDescription
namebodystringStatus name as the customer wants to see it. Unique within the product
colorbodystringDisplay colour as a six-digit hex string, e.g. #2563eb
orderbodyintegerSort order within the status dictionary, lowest first
categorybodystringone of: open, pending, resolved, closedLifecycle bucket the status belongs to. Automation and reporting read the category, never the name — so it cannot be changed once threads sit on the status

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Status id
namestringStatus name, unique within the product
colorstringDisplay colour as a hex string
orderintegerSort order within the status dictionary
archivedbooleanArchived statuses stay readable but are not offered as targets
categorystringone of: open, pending, resolved, closedLifecycle bucket the status belongs to
PATCH/support/statuses/:id

Rename, recolour or reorder a status. The category may only change while no thread references the status: changing it later would rewrite the history of every metric derived from it. A status belonging to another product is reported as not found

MCP tool: support_status_update

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Status id
namebodystringStatus name as the customer wants to see it. Unique within the product
colorbodystringDisplay colour as a six-digit hex string, e.g. #2563eb
orderbodyintegerSort order within the status dictionary, lowest first
categorybodystringone of: open, pending, resolved, closedNew lifecycle bucket. Refused while any thread references the status

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Status id
namestringStatus name, unique within the product
colorstringDisplay colour as a hex string
orderintegerSort order within the status dictionary
archivedbooleanArchived statuses stay readable but are not offered as targets
categorystringone of: open, pending, resolved, closedLifecycle bucket the status belongs to
POST/support/statuses/:id/archive

Retire a status. There is no way to delete one: every thread on it moves to the target status in the same transaction, so no thread is ever left on an archived status. The target must be a different, live status of this product

MCP tool: support_status_archive

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Status id
targetStatusIdbodystring (uuid)Live status every thread on the archived status moves to, in the same transaction

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Status id
namestringStatus name, unique within the product
colorstringDisplay colour as a hex string
orderintegerSort order within the status dictionary
archivedbooleanArchived statuses stay readable but are not offered as targets
categorystringone of: open, pending, resolved, closedLifecycle bucket the status belongs to
GET/support/surveys

List this product’s surveys, newest first, optionally narrowed to one lifecycle state (draft, published or archived), with pagination

MCP tool: support_survey_list

Parameters

NameInTypeRequiredDescription
statusquerystringone of: draft, published, archivedOnly surveys in this lifecycle state
limitqueryintegerPage size, 1..100 (default 25)
offsetqueryintegerNumber of surveys to skip

Response

Returns object.

FieldTypeAlwaysDescription
limitintegerPage size that was applied
offsetintegerOffset that was applied
surveysobject[]The requested page of surveys, newest first
POST/support/surveys

Open a new survey. It starts as a draft — editable and not yet answerable — whatever questions travel with it. There is no way to create one already published: publishing runs the structure validator, and a create that skipped it would be a second way in

MCP tool: support_survey_create

Parameters

NameInTypeRequiredDescription
namebodystringWhat this survey is called. It becomes the title of an escalated feedback thread
questionsbodyobject[]The initial question set. Omit it to open an empty draft and fill it in later

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Survey id
namestringWhat this survey is called
statusstringone of: draft, published, archiveddraft: editable, not answerable. published: answerable, frozen. archived: terminal, neither editable nor answerable, and there is no way back
createdAtstringISO-8601 creation timestamp
questionsobject[]The ordered question set, exactly as stored
updatedAtstringISO-8601 last-modification timestamp
GET/support/surveys/:id

Get one survey by id, with its whole question set. A survey belonging to another product is reported as not found. Through the public edge only a PUBLISHED survey is readable — a draft or an archived one is reported as not found there

MCP tool: support_survey_get

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Survey id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Survey id
namestringWhat this survey is called
statusstringone of: draft, published, archiveddraft: editable, not answerable. published: answerable, frozen. archived: terminal, neither editable nor answerable, and there is no way back
createdAtstringISO-8601 creation timestamp
questionsobject[]The ordered question set, exactly as stored
updatedAtstringISO-8601 last-modification timestamp
PATCH/support/surveys/:id

Edit a survey’s name or question set. Only a draft is editable — publishing freezes the structure, because answers are keyed by question id and rewriting the questions under them would change what every collected response was answering. To edit a live survey, unpublish it first. questions replaces the whole set; pass an empty array to clear it

MCP tool: support_survey_update

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Survey id
namebodystringNew name
questionsbodyobject[]The complete new question set, replacing the old one. Pass [] to empty the draft

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Survey id
namestringWhat this survey is called
statusstringone of: draft, published, archiveddraft: editable, not answerable. published: answerable, frozen. archived: terminal, neither editable nor answerable, and there is no way back
createdAtstringISO-8601 creation timestamp
questionsobject[]The ordered question set, exactly as stored
updatedAtstringISO-8601 last-modification timestamp
POST/support/surveys/:id/archive

Switch a survey off for good, from either draft or published. Archiving is terminal — there is no way back in v2 — and it deletes nothing: every response already collected stays readable

MCP tool: support_survey_archive

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Survey id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Survey id
namestringWhat this survey is called
statusstringone of: draft, published, archiveddraft: editable, not answerable. published: answerable, frozen. archived: terminal, neither editable nor answerable, and there is no way back
createdAtstringISO-8601 creation timestamp
questionsobject[]The ordered question set, exactly as stored
updatedAtstringISO-8601 last-modification timestamp
POST/support/surveys/:id/publish

Publish a draft survey, which is what makes it answerable and what freezes its structure. Publishing validates the whole question set: it must be non-empty, question ids must be unique, radio and checkbox questions must offer options, a statement may not be required, and every skip must target a later question or the literal "end". A survey that is already published or archived is refused

MCP tool: support_survey_publish

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Survey id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Survey id
namestringWhat this survey is called
statusstringone of: draft, published, archiveddraft: editable, not answerable. published: answerable, frozen. archived: terminal, neither editable nor answerable, and there is no way back
createdAtstringISO-8601 creation timestamp
questionsobject[]The ordered question set, exactly as stored
updatedAtstringISO-8601 last-modification timestamp
GET/support/surveys/:id/stats

Aggregate one survey’s responses over a time window: how many came in and how many reached the end, then per question — option counts for radio and checkbox, mean and distribution for rating and nps, an answered count for the rest. For the FIRST nps question it also returns promoters (9-10), passives (7-8), detractors (0-6) and the NPS score: percentage of promoters minus percentage of detractors over everyone who answered, rounded once. The window defaults to the last 30 days — omitting from does not mean "since the beginning"

MCP tool: support_survey_stats

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Survey id
fromquerystring (date-time)Start of the window, ISO-8601, inclusive. Defaults to 30 days ago — omitting it means "recently", never "since the beginning"
toquerystring (date-time)End of the window, ISO-8601, inclusive. Defaults to now

Response

Returns object.

FieldTypeAlwaysDescription
tostringISO-8601 end of the window that was actually applied
npsobject | nullThe NPS block, or null when the survey asks no nps question
fromstringISO-8601 start of the window that was actually applied
surveyIdstring (uuid)The survey these numbers describe
questionsobject[]Every question of the survey, answered or not
responsesobjectThe response counts over the window
POST/support/surveys/:id/unpublish

Return a published survey to draft so it can be edited. It stops accepting responses immediately; the responses already collected are untouched. A survey that is not published is refused

MCP tool: support_survey_unpublish

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Survey id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Survey id
namestringWhat this survey is called
statusstringone of: draft, published, archiveddraft: editable, not answerable. published: answerable, frozen. archived: terminal, neither editable nor answerable, and there is no way back
createdAtstringISO-8601 creation timestamp
questionsobject[]The ordered question set, exactly as stored
updatedAtstringISO-8601 last-modification timestamp
GET/support/threads

List support threads for this product, newest first — by creation time by default, or by last modification with sort='updated'. Every filter lives here: type, status, status category, assignee, external author, creation window, rating range (ratingMin/ratingMax, inclusive — a thread nobody rated matches neither bound), plus pagination

MCP tool: support_thread_list

Parameters

NameInTypeRequiredDescription
typequerystringone of: ticket, feedbackOnly threads of this type
statusIdquerystring (uuid)Only threads sitting on this exact status
categoryquerystringone of: open, pending, resolved, closedOnly threads whose status belongs to this category. Resolved through a join on the status dictionary — the category is never stored on the thread
assignedAgentIdquerystring (uuid)Only threads assigned to this agent
authorExternalIdquerystringOnly threads opened by this external author, matched verbatim
createdFromquerystring (date-time)Only threads created at or after this ISO-8601 timestamp
createdToquerystring (date-time)Only threads created at or before this ISO-8601 timestamp
ratingMinqueryintegerOnly threads rated at or above this score (0..10, inclusive). An unrated thread never matches a rating filter — not even at the bottom of the scale
ratingMaxqueryintegerOnly threads rated at or below this score (0..10, inclusive). An unrated thread never matches a rating filter — not even at the bottom of the scale
labelIdsquerystring (uuid) | string (uuid)[]Only threads carrying ALL of these labels. Every other filter here narrows the result and so does this one: each additional label id makes the answer smaller, never bigger
sortquerystringone of: created, updatedOrdering of the page, newest first either way (default 'created')
limitqueryintegerPage size, 1..100 (default 25)
offsetqueryintegerNumber of threads to skip

Response

Returns object.

FieldTypeAlwaysDescription
limitintegerPage size that was applied
offsetintegerOffset that was applied
threadsobject[]The requested page of threads, newest first by the requested sort
POST/support/threads

Open a support thread on behalf of an external end user. The author is an opaque identifier from the client's own user base and is stored verbatim. The thread opens on the product's default open status; there is no status argument. An optional rating — an integer 0..10, both ends inclusive — may travel with it and is stored verbatim too; omit it for an unrated thread, because 0 is a real score at the bottom of the scale

MCP tool: support_thread_create

Parameters

NameInTypeRequiredDescription
typebodystringone of: ticket, feedbackticket: the end user wants something fixed. feedback: unsolicited input
titlebodystringShort human-readable subject of the thread
authorExternalIdbodystringOpaque identifier of the external end user in the client's own user base. Stored verbatim: never resolved, normalised or enriched, and it is not a Lessly identity
authorDisplaybodystringOptional display name for the external author, as the client already knows it
metadatabodyobjectFree-form client-owned JSON attached to the thread
labelIdsbodystring (uuid)[]Labels to put on the new thread
ratingbodyintegerOptional score the client attached when the thread was opened: an integer 0..10, both ends inclusive, stored verbatim and never recomputed. Omit it for an unrated thread — 0 is a real score at the bottom of the scale, not a way of saying "no rating"

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Thread id
typestringone of: ticket, feedbackticket: the end user wants something fixed. feedback: unsolicited input
titlestringThread subject
labelsobject[]Every label on the thread, by name
ratinginteger | nullThe score the client supplied at creation, or null while the thread is unrated
statusobjectThe status itself, joined in at read time
metadataobjectFree-form client-owned JSON
prioritystringone of: low, normal, high, urgentThread priority
statusIdstring (uuid)Id of the status the thread sits on
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-modification timestamp
lastReplyAtstring | nullISO-8601 timestamp of the last reply, or null while there are none
authorDisplaystring | nullDisplay name for the external author, if given
assignedAgentIdstring (uuid) | nullAssigned agent, or null while unassigned
authorExternalIdstringThe external author, byte-identical to what was stored
GET/support/threads/:id

Get one support thread by id, with its status joined in. A thread belonging to another product is reported as not found

MCP tool: support_thread_get

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Thread id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Thread id
typestringone of: ticket, feedbackticket: the end user wants something fixed. feedback: unsolicited input
titlestringThread subject
labelsobject[]Every label on the thread, by name
ratinginteger | nullThe score the client supplied at creation, or null while the thread is unrated
statusobjectThe status itself, joined in at read time
metadataobjectFree-form client-owned JSON
prioritystringone of: low, normal, high, urgentThread priority
statusIdstring (uuid)Id of the status the thread sits on
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-modification timestamp
lastReplyAtstring | nullISO-8601 timestamp of the last reply, or null while there are none
authorDisplaystring | nullDisplay name for the external author, if given
assignedAgentIdstring (uuid) | nullAssigned agent, or null while unassigned
authorExternalIdstringThe external author, byte-identical to what was stored
PATCH/support/threads/:id

Edit a thread: its title, its priority, its labels and its client-owned metadata. Moving a thread between statuses and putting an agent on it have their own tools and are not possible here. labelIds replaces the entire label set — pass an empty array to clear it, and a label belonging to another product is reported as not found

MCP tool: support_thread_update

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Thread id
titlebodystringNew subject of the thread
prioritybodystringone of: low, normal, high, urgentNew priority
labelIdsbodystring (uuid)[]The complete new label set. Pass an empty array to remove every label
metadatabodyobjectReplaces the whole client-owned metadata object

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Thread id
typestringone of: ticket, feedbackticket: the end user wants something fixed. feedback: unsolicited input
titlestringThread subject
labelsobject[]Every label on the thread, by name
ratinginteger | nullThe score the client supplied at creation, or null while the thread is unrated
statusobjectThe status itself, joined in at read time
metadataobjectFree-form client-owned JSON
prioritystringone of: low, normal, high, urgentThread priority
statusIdstring (uuid)Id of the status the thread sits on
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-modification timestamp
lastReplyAtstring | nullISO-8601 timestamp of the last reply, or null while there are none
authorDisplaystring | nullDisplay name for the external author, if given
assignedAgentIdstring (uuid) | nullAssigned agent, or null while unassigned
authorExternalIdstringThe external author, byte-identical to what was stored
POST/support/threads/:id/assignment

Put a support agent on a thread, or pass null to return it to the unassigned queue — clearing an assignment is an ordinary operation, not an error. An agent belonging to another product is reported as not found

MCP tool: support_thread_assign

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Thread id
agentIdbodystring (uuid) | nullSupport agent of this product to put on the thread, or null to return it to the unassigned queue. An agent of another product is reported as not found

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Thread id
typestringone of: ticket, feedbackticket: the end user wants something fixed. feedback: unsolicited input
titlestringThread subject
labelsobject[]Every label on the thread, by name
ratinginteger | nullThe score the client supplied at creation, or null while the thread is unrated
statusobjectThe status itself, joined in at read time
metadataobjectFree-form client-owned JSON
prioritystringone of: low, normal, high, urgentThread priority
statusIdstring (uuid)Id of the status the thread sits on
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-modification timestamp
lastReplyAtstring | nullISO-8601 timestamp of the last reply, or null while there are none
authorDisplaystring | nullDisplay name for the external author, if given
assignedAgentIdstring (uuid) | nullAssigned agent, or null while unassigned
authorExternalIdstringThe external author, byte-identical to what was stored
POST/support/threads/:id/status

Move a thread to a status. Any status may follow any other — there are no transition rules. The category is never a parameter: it comes from the status the thread lands on. A status belonging to another product is reported as not found, and an archived status is refused

MCP tool: support_thread_status_set

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Thread id
statusIdbodystring (uuid)Destination status of this product. Any status may follow any other — v1 has no transition rules. An archived status is refused

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Thread id
typestringone of: ticket, feedbackticket: the end user wants something fixed. feedback: unsolicited input
titlestringThread subject
labelsobject[]Every label on the thread, by name
ratinginteger | nullThe score the client supplied at creation, or null while the thread is unrated
statusobjectThe status itself, joined in at read time
metadataobjectFree-form client-owned JSON
prioritystringone of: low, normal, high, urgentThread priority
statusIdstring (uuid)Id of the status the thread sits on
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-modification timestamp
lastReplyAtstring | nullISO-8601 timestamp of the last reply, or null while there are none
authorDisplaystring | nullDisplay name for the external author, if given
assignedAgentIdstring (uuid) | nullAssigned agent, or null while unassigned
authorExternalIdstringThe external author, byte-identical to what was stored
GET/support/webhook-deliveries

List webhook delivery attempts for this product, newest first. Filter by endpoint, by state (pending, delivered, failed), by event type or by the time the delivery was opened. Each row carries the exact JSON body that was sent, the last HTTP status and, while attempts remain, when the next one is due

MCP tool: support_webhook_deliveries_list

Parameters

NameInTypeRequiredDescription
webhookIdquerystring (uuid)Only deliveries for this endpoint
statequerystringone of: pending, delivered, failedOnly deliveries in this state: pending, delivered or failed
eventTypequerystringone of: support.message.created, support.thread.status-changed, support.thread.assigned, support.survey.published, support.response.createdOnly deliveries of this event type
createdFromquerystring (date-time)Only deliveries opened at or after this ISO-8601 time
createdToquerystring (date-time)Only deliveries opened at or before this ISO-8601 time
limitqueryintegerPage size, 1..200 (default 50)
offsetqueryintegerNumber of deliveries to skip

Response

Returns object.

FieldTypeAlwaysDescription
limitintegerPage size that was applied
offsetintegerOffset that was applied
deliveriesobject[]The requested page, newest first
POST/support/webhook-deliveries/redeliver

Send a past delivery to its endpoint again, with the original payload and the original idempotencyKey — a receiver that already processed it can recognise and ignore the repeat. The original delivery row is kept as history and a new one is opened for this attempt. If the endpoint has since been disabled or unsubscribed from the event, nothing is delivered

MCP tool: support_webhook_redeliver

Parameters

NameInTypeRequiredDescription
idbodystring (uuid)Id of the delivery to send again

Response

Returns object.

FieldTypeAlwaysDescription
deliveryobjectThe new delivery, opened in pending state. It carries the original idempotencyKey, so a receiver that already processed the first one can ignore it
GET/support/webhooks

List the endpoints this product has registered, oldest first. Signing secrets are never included — only the short prefix that tells two endpoints apart

MCP tool: support_webhook_list

Parameters

No parameters.

Response

Returns object.

FieldTypeAlwaysDescription
webhooksobject[]The endpoints this product has registered, oldest first
POST/support/webhooks

Register an HTTPS endpoint to receive Support events for this product, and mint its signing secret. The secret is returned here in clear and NOWHERE ELSE — exactly once, so store it now: it cannot be read back and can only be replaced by rotating it. Plain http:// endpoints are rejected

MCP tool: support_webhook_create

Parameters

NameInTypeRequiredDescription
urlbodystring (uri)HTTPS endpoint the event is POSTed to. Plain http:// is rejected
eventTypesbodystring[]one of: support.message.created, support.thread.status-changed, support.thread.assigned, support.survey.published, support.response.createdEvent types this endpoint subscribes to. One or more of support.message.created, support.thread.status-changed, support.thread.assigned, support.survey.published, support.response.created
descriptionbodystringFree-form note about what this endpoint is for, up to 1000 characters

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Webhook id
urlstringHTTPS endpoint events are POSTed to
secretstringThe signing secret in clear. Shown exactly once, here — store it now; it cannot be read back and can only be replaced by rotating it
statusstringone of: active, disabledactive or disabled
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-update timestamp
eventTypesstring[]Event types this endpoint subscribes to
descriptionstring | nullFree-form note, or null
secretPrefixstringFirst characters of the signing secret, to tell endpoints apart. Never the whole secret
DELETE/support/webhooks/:id

Remove a registered endpoint and the delivery history that points at it. To stop delivery without losing the registration, set its status to disabled instead

MCP tool: support_webhook_delete

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Webhook id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Id of the endpoint that was removed
deletedbooleanone of: trueAlways true — the endpoint is gone
GET/support/webhooks/:id

Get one registered endpoint by id. The signing secret is not part of the answer. An endpoint belonging to another product is reported as not found

MCP tool: support_webhook_get

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Webhook id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Webhook id
urlstringHTTPS endpoint events are POSTed to
statusstringone of: active, disabledactive or disabled
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-update timestamp
eventTypesstring[]Event types this endpoint subscribes to
descriptionstring | nullFree-form note, or null
secretPrefixstringFirst characters of the signing secret, to tell endpoints apart. Never the whole secret
PATCH/support/webhooks/:id

Edit a registered endpoint: its url, the event types it subscribes to, its description or its status. Setting status to disabled keeps the registration and stops delivery. Omit a field to leave it alone; pass null to clear the description. The signing secret is not editable here — rotate it instead

MCP tool: support_webhook_update

Parameters

NameInTypeRequiredDescription
urlbodystring (uri)HTTPS endpoint the event is POSTed to. Plain http:// is rejected
eventTypesbodystring[]one of: support.message.created, support.thread.status-changed, support.thread.assigned, support.survey.published, support.response.createdEvent types this endpoint subscribes to. One or more of support.message.created, support.thread.status-changed, support.thread.assigned, support.survey.published, support.response.created
descriptionbodystring | nullFree-form note about what this endpoint is for, up to 1000 characters
statusbodystringone of: active, disabledactive delivers events; disabled keeps the registration and stops delivery
idpathstring (uuid)Webhook id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Webhook id
urlstringHTTPS endpoint events are POSTed to
statusstringone of: active, disabledactive or disabled
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-update timestamp
eventTypesstring[]Event types this endpoint subscribes to
descriptionstring | nullFree-form note, or null
secretPrefixstringFirst characters of the signing secret, to tell endpoints apart. Never the whole secret
POST/support/webhooks/:id/rotate-secret

Replace the signing secret of an endpoint and return the new one in clear, exactly once. The old secret stops verifying immediately — there is no grace window, so update the receiver before rotating

MCP tool: support_webhook_rotate_secret

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)Webhook id

Response

Returns object.

FieldTypeAlwaysDescription
idstring (uuid)Webhook id
urlstringHTTPS endpoint events are POSTed to
secretstringThe signing secret in clear. Shown exactly once, here — store it now; it cannot be read back and can only be replaced by rotating it
statusstringone of: active, disabledactive or disabled
createdAtstringISO-8601 creation timestamp
updatedAtstringISO-8601 last-update timestamp
eventTypesstring[]Event types this endpoint subscribes to
descriptionstring | nullFree-form note, or null
secretPrefixstringFirst characters of the signing secret, to tell endpoints apart. Never the whole secret
Was this page helpful?
Esc

Start typing to search the docs.

navigateselect