{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/sitegpt-ai/json-schema/sitegpt-ai-conversation-schema.json",
  "title": "Conversation",
  "description": "A conversation thread between a visitor and the chatbot.",
  "x-generated": "2026-10-30",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/sitegpt-ai-openapi.json#/components/schemas/Conversation",
  "type": "object",
  "additionalProperties": true,
  "properties": {
    "threadId": {
      "type": "string"
    },
    "chatbotId": {
      "type": "string"
    },
    "mode": {
      "type": "string",
      "enum": [
        "AI",
        "AGENT"
      ],
      "description": "AI answers automatically; AGENT means human takeover."
    },
    "startedAt": {
      "type": "string",
      "format": "date-time"
    },
    "updatedAt": {
      "type": "string",
      "format": "date-time"
    },
    "endedAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "escalated": {
      "type": "boolean"
    },
    "important": {
      "type": "boolean"
    },
    "resolved": {
      "type": "boolean"
    },
    "title": {
      "type": [
        "string",
        "null"
      ]
    },
    "tagIds": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "sessionId": {
      "type": [
        "string",
        "null"
      ]
    },
    "ipAddress": {
      "type": [
        "string",
        "null"
      ]
    },
    "pageUrl": {
      "type": [
        "string",
        "null"
      ]
    },
    "source": {
      "type": "string",
      "enum": [
        "website",
        "api",
        "whatsapp",
        "messenger",
        "slack",
        "google_chat",
        "crisp",
        "freshdesk",
        "zoho_salesiq",
        "zendesk",
        "intercom",
        "email"
      ],
      "description": "Where the conversation started: website (the chat widget or the hosted chat page), api, or a connected channel."
    },
    "webhookUrl": {
      "type": [
        "string",
        "null"
      ]
    },
    "webhookTokenConfigured": {
      "type": "boolean"
    },
    "chatUserId": {
      "type": [
        "string",
        "null"
      ]
    },
    "chatUser": {
      "anyOf": [
        {
          "$ref": "#/$defs/ChatUser"
        },
        {
          "type": "null"
        }
      ]
    },
    "lead": {
      "anyOf": [
        {
          "$ref": "#/$defs/Lead"
        },
        {
          "type": "null"
        }
      ]
    },
    "totalMessages": {
      "type": "integer"
    },
    "totalPositiveMessages": {
      "type": "integer"
    },
    "totalNegativeMessages": {
      "type": "integer"
    },
    "totalGpt4MessagesCount": {
      "type": "integer"
    },
    "totalMessagesRead": {
      "type": "integer"
    },
    "totalMessagesReadByUser": {
      "type": "integer"
    },
    "unreadMessages": {
      "type": "integer"
    },
    "lastMessage": {
      "anyOf": [
        {
          "$ref": "#/$defs/Message"
        },
        {
          "type": "null"
        }
      ]
    },
    "messages": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Message"
      },
      "description": "Full message list; present on single-conversation reads and bulk action results, absent from list endpoints."
    }
  },
  "$defs": {
    "ChatUser": {
      "type": "object",
      "description": "A website visitor identified through the chat widget.",
      "additionalProperties": true,
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "phone": {
          "type": "string"
        },
        "verified": {
          "type": "boolean"
        },
        "createdAt": {
          "type": "string",
          "format": "date-time"
        },
        "updatedAt": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "GenericObject": {
      "type": "object",
      "additionalProperties": true
    },
    "Lead": {
      "type": "object",
      "description": "A captured lead. The top-level email convenience field is present on lead endpoints; conversation payloads embed the same record without it.",
      "additionalProperties": true,
      "properties": {
        "id": {
          "type": "string"
        },
        "chatbotId": {
          "type": "string"
        },
        "chatUser": {
          "$ref": "#/$defs/ChatUser"
        },
        "name": {
          "type": "string"
        },
        "phone": {
          "type": "string"
        },
        "email": {
          "type": "string",
          "description": "Convenience copy of chatUser.email."
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "customData": {
          "$ref": "#/$defs/GenericObject",
          "description": "Custom lead-form fields collected by the widget."
        },
        "important": {
          "type": "boolean"
        },
        "archived": {
          "type": "boolean"
        },
        "createdAt": {
          "type": "string",
          "format": "date-time"
        },
        "updatedAt": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "Message": {
      "type": "object",
      "description": "One stored conversation turn. NORMAL_MESSAGE carries the visitor question plus the AI answer; USER_MESSAGE and AGENT_MESSAGE carry one side of a human conversation; SYSTEM_MESSAGE records events such as escalation.",
      "additionalProperties": true,
      "properties": {
        "messageId": {
          "type": "string"
        },
        "messageType": {
          "type": "string",
          "description": "NORMAL_MESSAGE, USER_MESSAGE, AGENT_MESSAGE, or SYSTEM_MESSAGE."
        },
        "systemMessageType": {
          "type": [
            "string",
            "null"
          ],
          "description": "Set on SYSTEM_MESSAGE rows; null otherwise."
        },
        "question": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": true,
              "properties": {
                "text": {
                  "type": "string"
                },
                "timestamp": {
                  "type": "string"
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "answer": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": true,
              "properties": {
                "text": {
                  "type": "string"
                },
                "timestamp": {
                  "type": "string"
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "reaction": {
          "type": "string",
          "enum": [
            "POSITIVE",
            "NEGATIVE",
            "NEUTRAL"
          ]
        },
        "gptModel": {
          "type": [
            "string",
            "null"
          ],
          "description": "Public model label for AI answers; null on human turns."
        },
        "sources": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The page URL of each knowledge passage the AI was given for this answer, in retrieval order (best match first). A page with several passages appears several times. Answers sent through this API keep an empty string for each passage from uploaded files or text; answers from the chat widget leave those out."
        },
        "agentId": {
          "type": [
            "string",
            "null"
          ]
        },
        "agentName": {
          "type": [
            "string",
            "null"
          ]
        },
        "iconUrl": {
          "type": [
            "string",
            "null"
          ]
        },
        "createdAt": {
          "type": "string",
          "format": "date-time"
        },
        "updatedAt": {
          "type": "string",
          "format": "date-time"
        }
      }
    }
  }
}