ruLog in to Senler

Message data

An ask answer, getMessages history, subscribeDialog messages, and a messageReceived event share message data. Use it for a result next to a form or for a custom chat.

Text and identifiers

  • dialogId and eventId identify the dialog and message.
  • text contains the text; format is plain_text or markdown.
  • attachments contains files; buttons contains button rows.

An empty text is not necessarily an error: the answer may contain only a file. Render plain text with textContent and Markdown with a renderer that sanitizes unsafe HTML. Do not insert received text directly into innerHTML.

Versions, sender, and errors

FieldHow to use it
kindmessage is a regular message; error is a saved public error.
errorOn failure, may contain a visitor-facing message. It does not contain an internal exception stack.
versionMessage version: updates an existing entry with the same eventId, including attachment and button changes.
timestampMessage time for display and sorting.
sendervisitor, assistant, operator, or system. The messageReceived event is restricted to assistant and operator.
senderId, senderName, senderAvatarUrlOptional sender details; the avatar URL can also be null.
sendingStatusOptional sending status. It does not replace the final ask request status; handle missing or unfamiliar values.
deletedThe message was deleted: remove its content or display a deletion marker.

Merge messages within one dialog by eventId, respecting version. The mergeWidgetMessages(previous, incoming) export from @senlerio/widget does this and sorts the result by time. It retains entries marked deleted, so the interface must hide their content. Do not append an answer twice if it arrives through both ask and a subscription. See the custom chat merging example.

Attachments

Each attachment has id, type, and status. Its type can be photo, video, document, voice, audio, or sticker.

status: "ready" means the file is available. deferred, pending, fetching, and uploading indicate preparation; quota_pending means waiting for available quota, and failed means an error. An errorCode may accompany a failure. A URL is not necessarily available immediately.

Additional fields, when known:

  • url: the file; previewUrl: a preview image;
  • name, mimeType, size: filename, MIME type, and size in bytes;
  • width, height: image or video dimensions;
  • durationSeconds: audio or video duration in seconds.

To send a visitor's file, use uploadFile first, then pass its result to ask.

Buttons

buttons is an array of rows shaped as { buttons: [...] }. Each button has text and action. The action is an open_url link, a callback reply, or a registered custom_action on the website.

Optional fields describe state and appearance:

  • instanceId: button instance identifier;
  • repeatable: repeated clicks are allowed; disabled: the button is disabled;
  • appearance: neutral, primary, positive, or negative;
  • pollOption.multiple: a poll option allowing multiple selections.

Receiving button data does not mean the user clicked it or confirmed its action. In your custom interface's click handler, pass the original button to clickButton:

async function clickMessageButton(message, button) {
  if (button.disabled) return;
  await widget.clickButton({
    dialogId: message.dialogId,
    eventId: message.eventId,
    button,
  });
}

widget is a ready SDK instance; message and button are received data. Handle Promise rejection in the interface. The server checks callback identity, permissions, and repeatability. For a multiple-choice poll, pass pollSelectedInstanceIds containing the selected instanceId values with the confirmation button. Do not dispatch an action when rendering history.

For custom_action, use registered handlers. Resolving clickButton confirms dispatch, not completion of a later agent answer: the subscription will display it. For open_url, prefer a normal <a> with the returned URL to preserve keyboard navigation and browser behavior. Greeting buttons used before a dialog exists have a separate sending flow.