Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Conversation Export

The chatbot analytics events give you the front-end side of a chatbot session. This guide covers the other half: pulling the conversations themselves — the stored rating, topic, and where they were escalated to — into your own data warehouse, so chatbot journeys can be joined with traffic, order, and helpdesk data on your side.

Two endpoints do the work:

EndpointReturns
GET /api/v1/chat/conversationsConversation-level metadata and stored signals, paginated
GET /api/v1/chat/conversations/{id}One conversation including the full transcript

Both live under the management API and are documented in full in the API Reference.

Authentication

Use a chatbot API key with Basic auth, the same key used for the statistics and CSAT endpoints. The key prefix decides the environment: a live_ key only ever returns live conversations, a test_ key only test conversations.

curl https://api.dialogintelligens.dk/api/v1/chat/conversations?chatbot_id=YOUR_CHATBOT_ID \
  -u 'live_yourkey_yoursecret:'

What one conversation looks like

{
  "conversation_id": "conversation_42",
  "chatbot_id": "shop-bot",
  "environment": "live",
  "visitor_id": "visitor_123",
  "created_at": "2026-07-10T14:02:00.000Z",
  "updated_at": "2026-07-10T14:22:00.000Z",
  "message_count": 8,
  "topic": "Returnering",
  "tags": ["retur"],
  "customer_rating": 2,
  "rating_feedback": "Fik ikke svar på mit spørgsmål",
  "quality_score": 4,
  "fallback": true,
  "lacking_info": false,
  "escalation": {
    "livechat": false,
    "livechat_session_id": null,
    "livechat_requested_at": null,
    "support_ticket": true,
    "support_ticket_provider": "zendesk",
    "support_ticket_id": "48211",
    "support_ticket_status": "completed"
  },
  "source": "website",
  "split_test_id": null
}

Signals for good and bad journeys

Every field is stored as-is — the API does not classify a conversation as good or bad, so the definition stays yours. The fields worth building on:

FieldMeaning
customer_ratingThe visitor's own 1-5 rating, or null if they did not rate
rating_feedbackFree-text the visitor left with the rating
quality_scoreThe automatic 1-10 conversation score, or null if not scored
fallbackThe bot answered with its fallback response at least once
lacking_infoThe knowledge base was missing information for the question
escalationWhether and where the visitor was handed to a human (see below)
topicThe automatically classified topic, matching the dashboard

Following journeys into Zendesk or Freshdesk

When the visitor is handed over, escalation records where the journey continued:

  • livechat and livechat_session_id for conversations taken over by an agent in Diverge livechat.
  • support_ticket_provider and support_ticket_id for conversations that created a helpdesk ticket. support_ticket_id is the ticket number in Zendesk or Freshdesk, so it joins directly against your helpdesk data.

support_ticket_id is null while a ticket is still queued (support_ticket_status is pending or processing) and for tickets created before ticket linking was introduced; support_ticket still tells you the visitor submitted the form.

Narrow the list to escalated journeys with escalated=true, or to the ones the bot handled on its own with escalated=false.

Incremental syncs

updated_at is the export watermark. It is the most recent of conversation creation, rating submission, livechat session activity, and helpdesk ticket delivery — so a conversation that gets rated two days after it started shows up again in the next sync.

Store the highest updated_at you have loaded and pass it back as updated_since:

curl -G https://api.dialogintelligens.dk/api/v1/chat/conversations \
  -u 'live_yourkey_yoursecret:' \
  --data-urlencode 'chatbot_id=YOUR_CHATBOT_ID' \
  --data-urlencode 'updated_since=2026-07-09T00:00:00Z' \
  --data-urlencode 'limit=100'

When back-filling a large history, combine updated_since with a start_date/end_date window and walk the range month by month. start_date and end_date filter on created_at and must be supplied together.

Pagination

Results are ordered newest first and paginated with an opaque cursor. Keep requesting until next_cursor is null:

async function fetchAll(chatbotId, updatedSince) {
  const auth = Buffer.from(`${process.env.DIVERGE_API_KEY}:`).toString("base64");
  const conversations = [];
  let cursor = null;
 
  do {
    const url = new URL("https://api.dialogintelligens.dk/api/v1/chat/conversations");
    url.searchParams.set("chatbot_id", chatbotId);
    url.searchParams.set("limit", "100");
    if (updatedSince) url.searchParams.set("updated_since", updatedSince);
    if (cursor) url.searchParams.set("cursor", cursor);
 
    const response = await fetch(url, { headers: { Authorization: `Basic ${auth}` } });
    if (!response.ok) throw new Error(`Conversation export failed: ${response.status}`);
 
    const page = await response.json();
    conversations.push(...page.items);
    cursor = page.next_cursor;
  } while (cursor);
 
  return conversations;
}

Reading a transcript

Fetch a single conversation when you need the messages themselves — for example to review the low-rated conversations the list surfaced:

curl https://api.dialogintelligens.dk/api/v1/chat/conversations/conversation_42 \
  -u 'live_yourkey_yoursecret:'

The response is the same record plus form_data (the stored contact or support ticket form) and history, the full message list in the same shape the chatbot API uses everywhere else.

Transcripts contain whatever visitors typed, so treat them as personal data: pull them on demand for the conversations you actually need rather than mirroring every transcript into your warehouse.

Related