1
0
mirror of https://github.com/ZeroCatDev/Classworks.git synced 2025-12-07 21:13:11 +00:00

Add Chatwoot integration

This commit is contained in:
Sunwuyuan 2025-12-07 12:26:48 +08:00
parent 1831c9144d
commit 0e1e69f27d
No known key found for this signature in database
GPG Key ID: A6A54CF66F56BB64
256 changed files with 49196 additions and 0 deletions

681
src/pages/chatwoot.vue Normal file
View File

@ -0,0 +1,681 @@
<template>
<v-container class="py-8 chatwoot-page">
<v-row>
<v-col cols="12" md="4">
<v-card>
<v-card-title>
<div class="d-flex align-center justify-space-between w-100">
<span>Chatwoot 配置</span>
<v-btn
icon
size="small"
variant="text"
:loading="loadingInbox"
:disabled="!hasConnectionConfig"
@click="fetchInboxDetails"
>
<v-icon size="20">mdi-refresh</v-icon>
</v-btn>
</div>
</v-card-title>
<v-card-text>
<v-text-field
v-model="baseUrl"
label="Chatwoot Base URL"
placeholder="https://app.chatwoot.com"
prepend-inner-icon="mdi-earth"
/>
<v-text-field
v-model="inboxIdentifier"
label="Inbox Identifier"
prepend-inner-icon="mdi-inbox"
/>
<v-alert
v-if="inboxDetails"
type="info"
variant="tonal"
class="mt-4"
>
<div class="text-subtitle-2">{{ inboxDetails.name || `Inbox #${inboxDetails.id}` }}</div>
<div class="text-caption text-medium-emphasis">渠道{{ inboxDetails.channel_type }}</div>
</v-alert>
</v-card-text>
</v-card>
</v-col>
<v-col cols="12" md="8">
<v-card>
<v-card-title>
<div class="d-flex align-center justify-space-between w-100">
<span>联系人</span>
<div class="d-flex ga-2">
<v-btn
color="primary"
variant="flat"
:loading="creatingContact"
@click="createOrUpdateContact"
>
{{ contactIdentifier ? '更新联系人' : '创建联系人' }}
</v-btn>
<v-btn
variant="tonal"
:loading="loadingContact"
:disabled="!contactIdentifier"
@click="loadExistingContact"
>
重新获取
</v-btn>
</div>
</div>
</v-card-title>
<v-card-text>
<v-text-field
v-model="contactIdentifier"
label="Contact Source ID"
persistent-hint
hint="从创建接口返回的 source_id"
prepend-inner-icon="mdi-identifier"
/>
<v-text-field
v-model="contactForm.identifier"
label="外部标识 identifier"
prepend-inner-icon="mdi-account-key"
/>
<v-text-field
v-model="contactForm.name"
label="姓名"
prepend-inner-icon="mdi-account"
/>
<v-text-field
v-model="contactForm.email"
label="Email"
prepend-inner-icon="mdi-email"
/>
<v-text-field
v-model="contactForm.phone_number"
label="电话"
prepend-inner-icon="mdi-phone"
/>
<div class="text-caption text-medium-emphasis mt-2">
创建成功会自动填入 Source ID后续会话操作依赖该字段
</div>
<v-alert
v-if="contactDetails"
type="success"
variant="tonal"
class="mt-4"
>
<div>ID{{ contactDetails.id }}</div>
<div>Source ID{{ contactDetails.source_id }}</div>
<div v-if="contactDetails.email">Email{{ contactDetails.email }}</div>
</v-alert>
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row class="mt-4">
<v-col cols="12" md="4">
<v-card>
<v-card-title>
<div class="d-flex align-center justify-space-between w-100">
<span>会话</span>
<div class="d-flex ga-1">
<v-btn
icon
size="small"
variant="text"
:loading="loadingConversations"
:disabled="!contactReady"
@click="() => loadConversations({ refreshMessages: true })"
>
<v-icon size="20">mdi-refresh</v-icon>
</v-btn>
<v-btn
icon
size="small"
variant="text"
color="primary"
:loading="creatingConversation"
:disabled="!contactReady"
@click="createConversation"
>
<v-icon size="20">mdi-plus</v-icon>
</v-btn>
</div>
</div>
</v-card-title>
<v-divider />
<v-card-text class="py-0">
<v-list nav density="comfortable">
<v-list-item
v-for="conversation in conversations"
:key="conversation.id"
:value="conversation.id"
:active="conversation.id === selectedConversationId"
@click="selectConversation(conversation.id)"
>
<template #title>
<div class="d-flex flex-column">
<span class="font-weight-medium">#{{ conversation.id }}</span>
<span
v-if="conversation.latestMessage"
class="text-caption text-medium-emphasis ellipsis"
>
{{ conversation.latestMessage }}
</span>
</div>
</template>
<template #subtitle>
<span class="text-caption text-disabled">
{{ formatTimestamp(conversation.updated_at || conversation.created_at) }}
</span>
</template>
</v-list-item>
<v-list-item v-if="!loadingConversations && !conversations.length">
<v-list-item-title class="text-medium-emphasis">暂无会话</v-list-item-title>
</v-list-item>
</v-list>
</v-card-text>
</v-card>
</v-col>
<v-col cols="12" md="8">
<v-card class="conversation-card">
<v-card-title class="d-flex justify-space-between align-center">
<span v-if="selectedConversationId">会话 #{{ selectedConversationId }}</span>
<span v-else>选择一个会话以查看消息</span>
<v-btn
v-if="selectedConversationId"
variant="text"
color="success"
size="small"
:loading="resolvingConversation"
@click="resolveConversation"
>
设为已解决
</v-btn>
</v-card-title>
<v-divider />
<v-card-text class="conversation-messages">
<div v-if="loadingMessages" class="text-center py-6">
<v-progress-circular indeterminate color="primary" />
</div>
<template v-else>
<div
v-for="message in messages"
:key="message.id"
class="message-row"
:class="message.sender_type === 'contact' ? 'from-contact' : 'from-agent'"
>
<div class="message-meta">
<span class="message-sender">{{ message.sender_type === 'contact' ? '访客' : '坐席' }}</span>
<span class="message-time">{{ formatTimestamp(message.created_at) }}</span>
</div>
<div class="message-content">
<pre>{{ message.content || '(无文本内容)' }}</pre>
</div>
</div>
<div v-if="!messages.length" class="text-center text-medium-emphasis py-6">
暂无消息
</div>
</template>
</v-card-text>
<v-divider />
<v-card-text>
<v-form @submit.prevent="sendMessage">
<v-textarea
v-model="messageBody"
label="发送消息"
rows="3"
auto-grow
:disabled="!selectedConversationId"
/>
<div class="d-flex justify-end">
<v-btn
type="submit"
color="primary"
:disabled="!selectedConversationId || !messageBody.trim()"
:loading="sendingMessage"
>
发送
</v-btn>
</div>
</v-form>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script setup>
import { reactive, ref, computed, watch, onMounted, getCurrentInstance } from 'vue';
import axios from 'axios';
const defaultInbox = 'UJJfBp1gvojFcUJUor189i8U';
const storageKey = 'cw-chatwoot-console';
const baseUrl = ref('https://app.chatwoot.com');
const inboxIdentifier = ref(defaultInbox);
const contactIdentifier = ref('');
const contactForm = reactive({
identifier: '',
name: '',
email: '',
phone_number: '',
});
const inboxDetails = ref(null);
const contactDetails = ref(null);
const conversations = ref([]);
const selectedConversationId = ref(null);
const messages = ref([]);
const messageBody = ref('');
const loadingInbox = ref(false);
const creatingContact = ref(false);
const loadingContact = ref(false);
const loadingConversations = ref(false);
const creatingConversation = ref(false);
const loadingMessages = ref(false);
const sendingMessage = ref(false);
const resolvingConversation = ref(false);
const instance = getCurrentInstance();
const messenger = instance?.appContext.config.globalProperties.$message;
const notify = {
success: (title, content) => {
if (messenger?.success) {
messenger.success(title, content);
} else {
console.info(title, content);
}
},
error: (title, content) => {
if (messenger?.error) {
messenger.error(title, content);
} else {
console.error(title, content);
}
},
info: (title, content) => {
if (messenger?.info) {
messenger.info(title, content);
} else {
console.log(title, content);
}
},
};
const normalizedBaseUrl = computed(() => {
const value = baseUrl.value.trim();
if (!value) return '';
return value.endsWith('/') ? value.slice(0, -1) : value;
});
const hasConnectionConfig = computed(() => Boolean(normalizedBaseUrl.value && inboxIdentifier.value.trim()));
const inboxBaseUrl = computed(() => {
if (!hasConnectionConfig.value) return '';
const inboxId = encodeURIComponent(inboxIdentifier.value.trim());
return `${normalizedBaseUrl.value}/public/api/v1/inboxes/${inboxId}`;
});
const contactReady = computed(() => hasConnectionConfig.value && Boolean(contactIdentifier.value.trim()));
const hasHydrated = ref(false);
onMounted(() => {
if (typeof window === 'undefined') return;
try {
const cached = window.localStorage.getItem(storageKey);
if (cached) {
const parsed = JSON.parse(cached);
if (parsed.baseUrl) baseUrl.value = parsed.baseUrl;
if (parsed.inboxIdentifier) inboxIdentifier.value = parsed.inboxIdentifier;
if (parsed.contactIdentifier) contactIdentifier.value = parsed.contactIdentifier;
if (parsed.contactForm) {
Object.assign(contactForm, parsed.contactForm);
}
}
} catch (error) {
console.warn('无法解析缓存的 Chatwoot 配置', error);
} finally {
hasHydrated.value = true;
if (hasConnectionConfig.value) {
fetchInboxDetails();
}
if (contactReady.value) {
loadExistingContact();
}
}
});
const persistState = () => {
if (!hasHydrated.value || typeof window === 'undefined') return;
const payload = {
baseUrl: baseUrl.value,
inboxIdentifier: inboxIdentifier.value,
contactIdentifier: contactIdentifier.value,
contactForm: { ...contactForm },
};
try {
window.localStorage.setItem(storageKey, JSON.stringify(payload));
} catch (error) {
console.warn('保存 Chatwoot 配置失败', error);
}
};
watch([
baseUrl,
inboxIdentifier,
contactIdentifier,
() => contactForm.identifier,
() => contactForm.name,
() => contactForm.email,
() => contactForm.phone_number,
], persistState);
const ensureConnection = () => {
if (!hasConnectionConfig.value) {
notify.error('缺少配置', '请先填写 Base URL 与 Inbox Identifier');
return false;
}
return true;
};
const ensureContact = () => {
if (!contactReady.value) {
notify.error('缺少联系人信息', '请先创建联系人,或填入已有的 Source ID');
return false;
}
return true;
};
const extractErrorMessage = (error) => {
if (error.response?.data) {
const data = error.response.data;
if (typeof data === 'string') return data;
if (data.message) return data.message;
if (data.error) return data.error;
if (Array.isArray(data.errors)) return data.errors.join(', ');
}
return error.message || '未知错误';
};
const fetchInboxDetails = async () => {
if (!ensureConnection()) return;
loadingInbox.value = true;
try {
const { data } = await axios.get(inboxBaseUrl.value);
inboxDetails.value = data;
notify.success('已获取 Inbox 信息', inboxDetails.value.name || `Inbox #${inboxDetails.value.id}`);
} catch (error) {
notify.error('获取 Inbox 失败', extractErrorMessage(error));
} finally {
loadingInbox.value = false;
}
};
const createOrUpdateContact = async () => {
if (!ensureConnection()) return;
const payload = Object.fromEntries(
Object.entries(contactForm)
.filter(([, value]) => Boolean(value?.toString().trim()))
);
if (!payload.identifier && !payload.email) {
notify.error('缺少必填字段', '创建联系人至少需要 identifier 或 email');
return;
}
creatingContact.value = true;
try {
const hadIdentifier = Boolean(contactIdentifier.value);
if (hadIdentifier) {
const url = `${inboxBaseUrl.value}/contacts/${encodeURIComponent(contactIdentifier.value.trim())}`;
const { data } = await axios.patch(url, payload);
contactDetails.value = data;
notify.success('联系人已更新', `Source ID${data.source_id}`);
} else {
const { data } = await axios.post(`${inboxBaseUrl.value}/contacts`, payload);
contactDetails.value = data;
contactIdentifier.value = data.source_id;
notify.success('联系人已创建', `Source ID${data.source_id}`);
}
await loadConversations({ preserveSelection: hadIdentifier, refreshMessages: true });
} catch (error) {
notify.error('提交联系人失败', extractErrorMessage(error));
} finally {
creatingContact.value = false;
}
};
const loadExistingContact = async () => {
if (!ensureConnection() || !contactIdentifier.value) return;
loadingContact.value = true;
try {
const url = `${inboxBaseUrl.value}/contacts/${encodeURIComponent(contactIdentifier.value.trim())}`;
const { data } = await axios.get(url);
contactDetails.value = data;
notify.success('已获取联系人', data.name || data.source_id);
await loadConversations({ preserveSelection: false, refreshMessages: true });
} catch (error) {
notify.error('获取联系人失败', extractErrorMessage(error));
} finally {
loadingContact.value = false;
}
};
const loadConversations = async (options = {}) => {
if (!ensureContact()) return;
const { preserveSelection = true, refreshMessages = false } = options;
loadingConversations.value = true;
try {
const url = `${inboxBaseUrl.value}/contacts/${encodeURIComponent(contactIdentifier.value.trim())}/conversations`;
const { data } = await axios.get(url);
const normalized = (Array.isArray(data) ? data : []).map((item) => {
const latestMessage = item.messages?.length ? item.messages[item.messages.length - 1].content : '';
return {
...item,
latestMessage,
};
});
conversations.value = normalized;
const hasSelection = normalized.some((conv) => conv.id === selectedConversationId.value);
if (!preserveSelection || !selectedConversationId.value || !hasSelection) {
selectedConversationId.value = normalized[0]?.id ?? null;
}
if (selectedConversationId.value) {
if (!hasSelection || refreshMessages || !preserveSelection) {
await fetchMessages(selectedConversationId.value);
}
} else {
messages.value = [];
}
} catch (error) {
notify.error('加载会话失败', extractErrorMessage(error));
} finally {
loadingConversations.value = false;
}
};
const createConversation = async () => {
if (!ensureContact()) return;
creatingConversation.value = true;
try {
const url = `${inboxBaseUrl.value}/contacts/${encodeURIComponent(contactIdentifier.value.trim())}/conversations`;
const { data } = await axios.post(url, {});
notify.success('会话已创建', `ID${data.id}`);
await loadConversations({ preserveSelection: true });
selectedConversationId.value = data.id;
await fetchMessages(data.id);
} catch (error) {
notify.error('创建会话失败', extractErrorMessage(error));
} finally {
creatingConversation.value = false;
}
};
const fetchMessages = async (conversationId = selectedConversationId.value) => {
if (!ensureContact() || !conversationId) return;
loadingMessages.value = true;
try {
const url = `${inboxBaseUrl.value}/contacts/${encodeURIComponent(contactIdentifier.value.trim())}/conversations/${conversationId}/messages`;
const { data } = await axios.get(url);
const sorted = (Array.isArray(data) ? data : [])
.map((msg) => ({
...msg,
sender_type: msg.sender_type || (msg.message_type === 1 ? 'agent' : 'contact'),
}))
.sort((a, b) => (a.created_at ?? 0) - (b.created_at ?? 0));
messages.value = sorted;
await updateLastSeen(conversationId);
} catch (error) {
notify.error('加载消息失败', extractErrorMessage(error));
} finally {
loadingMessages.value = false;
}
};
const updateLastSeen = async (conversationId) => {
try {
const url = `${inboxBaseUrl.value}/contacts/${encodeURIComponent(contactIdentifier.value.trim())}/conversations/${conversationId}/update_last_seen`;
await axios.post(url);
} catch (error) {
console.debug('更新已读状态失败,可忽略', error);
}
};
const resolveConversation = async () => {
if (!ensureContact() || !selectedConversationId.value) return;
resolvingConversation.value = true;
try {
const url = `${inboxBaseUrl.value}/contacts/${encodeURIComponent(contactIdentifier.value.trim())}/conversations/${selectedConversationId.value}/toggle_status`;
await axios.post(url);
notify.success('会话已设置为已解决', `ID${selectedConversationId.value}`);
await loadConversations({ preserveSelection: true, refreshMessages: true });
} catch (error) {
notify.error('更新会话状态失败', extractErrorMessage(error));
} finally {
resolvingConversation.value = false;
}
};
const selectConversation = async (conversationId) => {
if (selectedConversationId.value === conversationId) return;
selectedConversationId.value = conversationId;
await fetchMessages(conversationId);
};
const sendMessage = async () => {
if (!ensureContact() || !selectedConversationId.value) return;
const content = messageBody.value.trim();
if (!content) return;
sendingMessage.value = true;
try {
const url = `${inboxBaseUrl.value}/contacts/${encodeURIComponent(contactIdentifier.value.trim())}/conversations/${selectedConversationId.value}/messages`;
await axios.post(url, { content });
messageBody.value = '';
await fetchMessages(selectedConversationId.value);
await loadConversations({ preserveSelection: true });
} catch (error) {
notify.error('发送消息失败', extractErrorMessage(error));
} finally {
sendingMessage.value = false;
}
};
const formatTimestamp = (timestamp) => {
if (!timestamp) return '';
try {
const date = new Date(timestamp * 1000);
if (Number.isNaN(date.getTime())) return '';
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;
} catch (error) {
return '';
}
};
</script>
<style scoped>
.chatwoot-page {
min-height: 100vh;
}
.conversation-card {
display: flex;
flex-direction: column;
min-height: 440px;
}
.conversation-messages {
flex: 1;
overflow-y: auto;
background: var(--v-theme-surface-variant, #f5f5f5);
border-radius: 12px;
padding: 16px;
border: 1px solid rgba(0, 0, 0, 0.06);
}
.message-row {
max-width: 72%;
display: flex;
flex-direction: column;
gap: 4px;
margin-bottom: 16px;
}
.message-row.from-agent {
align-self: flex-end;
text-align: right;
}
.message-row.from-contact {
align-self: flex-start;
text-align: left;
}
.message-meta {
display: flex;
justify-content: space-between;
font-size: 12px;
color: var(--v-theme-on-surface, #424242);
opacity: 0.65;
}
.message-content {
border-radius: 10px;
padding: 10px 12px;
background: var(--v-theme-surface, #ffffff);
color: var(--v-theme-on-surface, #1f1f1f);
white-space: pre-wrap;
word-break: break-word;
border: 1px solid rgba(0, 0, 0, 0.08);
}
.message-row.from-contact .message-content {
background: var(--v-theme-surface-variant, #f0f0f0);
}
.message-row.from-agent .message-content {
background: var(--v-theme-primary, #1976d2);
color: var(--v-theme-on-primary, #ffffff);
border-color: transparent;
}
.message-content pre {
margin: 0;
white-space: pre-wrap;
font-family: var(--v-font-family, inherit);
}
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

View File

@ -0,0 +1,9 @@
title: data
type: object
properties:
description:
type: string
errors:
type: array
items:
$ref: '#/components/schemas/request_error'

View File

@ -0,0 +1,8 @@
type: object
properties:
field:
type: string
message:
type: string
code:
type: string

View File

@ -0,0 +1,256 @@
## ---------- ERRORS -------------- ##
## -------------------------------- ##
bad_request_error:
$ref: ./error/bad_request.yml
request_error:
$ref: ./error/request.yml
## ---------- RESOURCE ------------ ##
## -------------------------------- ##
generic_id:
$ref: ./resource/extension/generic.yml
canned_response:
$ref: ./resource/canned_response.yml
custom_attribute:
$ref: ./resource/custom_attribute.yml
automation_rule:
$ref: ./resource/automation_rule.yml
automation_rule_item:
$ref: ./resource/automation_rule_item.yml
portal:
$ref: ./resource/portal.yml
portal_single:
$ref: ./resource/portal_single.yml
portal_config:
$ref: ./resource/portal_config.yml
portal_logo:
$ref: ./resource/portal_logo.yml
portal_meta:
$ref: ./resource/portal_meta.yml
portal_item:
$ref: ./resource/portal_item.yml
category:
$ref: ./resource/category.yml
article:
$ref: ./resource/article.yml
contact:
$ref: ./resource/contact.yml
conversation:
$ref: ./resource/conversation.yml
message:
$ref: ./resource/message.yml
user:
$ref: ./resource/user.yml
agent:
$ref: ./resource/agent.yml
inbox:
$ref: ./resource/inbox.yml
inbox_contact:
$ref: ./resource/inbox_contact.yml
agent_bot:
$ref: ./resource/agent_bot.yml
contact_inboxes:
$ref: ./resource/contact_inboxes.yml
contactable_inboxes:
$ref: ./resource/contactable_inboxes.yml
custom_filter:
$ref: ./resource/custom_filter.yml
webhook:
$ref: ./resource/webhook.yml
account:
$ref: ./resource/account.yml
account_detail:
$ref: ./resource/account_detail.yml
account_show_response:
$ref: ./resource/account_show_response.yml
account_user:
$ref: ./resource/account_user.yml
platform_account:
$ref: ./resource/platform_account.yml
team:
$ref: ./resource/team.yml
integrations_app:
$ref: ./resource/integrations/app.yml
integrations_hook:
$ref: ./resource/integrations/hook.yml
audit_log:
$ref: ./resource/audit_log.yml
## public resources
public_contact:
$ref: ./resource/public/contact.yml
public_conversation:
$ref: ./resource/public/conversation.yml
public_message:
$ref: ./resource/public/message.yml
public_inbox:
$ref: ./resource/public/inbox.yml
## ---------- REQUEST ------------- ##
## -------------------------------- ##
account_create_update_payload:
$ref: ./request/account/create_update_payload.yml
account_update_payload:
$ref: ./request/account/update_payload.yml
account_user_create_update_payload:
$ref: ./request/account_user/create_update_payload.yml
platform_agent_bot_create_update_payload:
$ref: ./request/platform/agent_bot/create_update_payload.yml
agent_bot_create_update_payload:
$ref: ./request/agent_bot/create_update_payload.yml
user_create_update_payload:
$ref: ./request/user/create_update_payload.yml
canned_response_create_update_payload:
$ref: ./request/canned_response/create_update_payload.yml
custom_attribute_create_update_payload:
$ref: ./request/custom_attribute/create_update_payload.yml
## Agent
agent_create_payload:
$ref: ./request/agent/create_payload.yml
agent_update_payload:
$ref: ./request/agent/update_payload.yml
## Contact
contact_create_payload:
$ref: ./request/contact/create_payload.yml
contact_update_payload:
$ref: ./request/contact/update_payload.yml
## Conversation
conversation_create_payload:
$ref: ./request/conversation/create_payload.yml
conversation_message_create_payload:
$ref: ./request/conversation/create_message_payload.yml
# Inbox
inbox_create_payload:
$ref: ./request/inbox/create_payload.yml
inbox_update_payload:
$ref: ./request/inbox/update_payload.yml
# Team
team_create_update_payload:
$ref: ./request/team/create_update_payload.yml
# Custom Filter
custom_filter_create_update_payload:
$ref: ./request/custom_filter/create_update_payload.yml
webhook_create_update_payload:
$ref: ./request/webhooks/create_update_payload.yml
integrations_hook_create_payload:
$ref: ./request/integrations/hook_create_payload.yml
integrations_hook_update_payload:
$ref: ./request/integrations/hook_update_payload.yml
# Automation Rule
automation_rule_create_update_payload:
$ref: ./request/automation_rule/create_update_payload.yml
# Help Center
portal_create_update_payload:
$ref: ./request/portal/portal_create_update_payload.yml
category_create_update_payload:
$ref: ./request/portal/category_create_update_payload.yml
article_create_update_payload:
$ref: ./request/portal/article_create_update_payload.yml
## public requests
public_contact_create_update_payload:
$ref: ./request/public/contact/create_update_payload.yml
public_message_create_payload:
$ref: ./request/public/message/create_payload.yml
public_message_update_payload:
$ref: ./request/public/message/update_payload.yml
public_conversation_create_payload:
$ref: ./request/public/conversation/create_payload.yml
## ---------- RESPONSE ------------ ##
## -------------------------------- ##
## Contact
extended_contact:
allOf:
- $ref: '#/components/schemas/contact'
- $ref: ./resource/extension/contact/show.yml
contact_base:
allOf:
- $ref: '#/components/schemas/generic_id'
- $ref: '#/components/schemas/contact'
contact_list:
type: array
description: 'array of contacts'
items:
allOf:
- $ref: '#/components/schemas/contact'
contact_conversations:
type: array
description: 'array of conversations'
items:
allOf:
- $ref: '#/components/schemas/conversation'
- $ref: ./resource/extension/contact/conversation.yml
- $ref: ./resource/extension/conversation/with_display_id.yml
contact_labels:
$ref: ./resource/extension/contact/labels.yml
## Conversation
conversation_list:
$ref: ./resource/extension/conversation/list.yml
conversation_show:
$ref: ./resource/extension/conversation/show.yml
conversation_status_toggle:
$ref: ./resource/extension/conversation/status_toggle.yml
conversation_labels:
$ref: ./resource/extension/conversation/labels.yml
## Report
account_summary:
$ref: './resource/reports/summary.yml'
agent_conversation_metrics:
$ref: './resource/reports/conversation/agent.yml'
contact_detail:
$ref: ./resource/contact_detail.yml
message_detailed:
$ref: ./resource/message_detailed.yml
conversation_meta:
$ref: ./resource/conversation_meta.yml
conversation_messages:
$ref: ./resource/conversation_messages.yml
contact_meta:
$ref: ./resource/contact_meta.yml
contact_inbox:
$ref: ./resource/contact_inbox.yml
contact_list_item:
$ref: ./resource/contact_list_item.yml
contacts_list_response:
$ref: ./resource/contacts_list_response.yml
contact_show_response:
$ref: ./resource/contact_show_response.yml
contact_conversation_message:
$ref: ./resource/contact_conversation_message.yml
contact_conversations_response:
$ref: ./resource/contact_conversations_response.yml
contactable_inboxes_response:
$ref: ./resource/contactable_inboxes_response.yml
reporting_event:
$ref: ./resource/reporting_event.yml
reporting_event_meta:
$ref: ./resource/reporting_event_meta.yml
reporting_events_list_response:
$ref: ./resource/reporting_events_list_response.yml

View File

@ -0,0 +1,31 @@
type: object
properties:
name:
type: string
description: Name of the account
example: 'My Account'
locale:
type: string
description: The locale of the account
example: 'en'
domain:
type: string
description: The domain of the account
example: 'example.com'
support_email:
type: string
description: The support email of the account
example: 'support@example.com'
status:
type: string
enum: ['active', 'suspended']
description: The status of the account
example: 'active'
limits:
type: object
description: The limits of the account
example: {}
custom_attributes:
type: object
description: The custom attributes of the account
example: {}

View File

@ -0,0 +1,49 @@
type: object
properties:
name:
type: string
description: Name of the account
example: 'My Account'
locale:
type: string
description: The locale of the account
example: 'en'
domain:
type: string
description: The domain of the account
example: 'example.com'
support_email:
type: string
description: The support email of the account
example: 'support@example.com'
# Settings parameters (stored in settings JSONB column)
auto_resolve_after:
type: integer
minimum: 10
maximum: 1439856
nullable: true
description: Auto resolve conversations after specified minutes
example: 1440
auto_resolve_message:
type: string
nullable: true
description: Message to send when auto resolving
example: "This conversation has been automatically resolved due to inactivity"
auto_resolve_ignore_waiting:
type: boolean
nullable: true
description: Whether to ignore waiting conversations for auto resolve
example: false
# Custom attributes parameters (stored in custom_attributes JSONB column)
industry:
type: string
description: Industry type
example: "Technology"
company_size:
type: string
description: Company size
example: "50-100"
timezone:
type: string
description: Account timezone
example: "UTC"

View File

@ -0,0 +1,13 @@
type: object
required:
- user_id
- role
properties:
user_id:
type: integer
description: The ID of the user
example: 1
role:
type: string
description: whether user is an administrator or agent
example: administrator

View File

@ -0,0 +1,28 @@
type: object
required:
- name
- email
- role
properties:
name:
type: string
description: Full Name of the agent
example: 'John Doe'
email:
type: string
description: Email of the Agent
example: 'john.doe@acme.inc'
role:
type: string
enum: ['agent', 'administrator']
description: Whether its administrator or agent
example: 'agent'
availability_status:
type: string
enum: ['available', 'busy', 'offline']
description: The availability setting of the agent.
example: 'available'
auto_offline:
type: boolean
description: Whether the availability status of agent is configured to go offline automatically when away.
example: true

View File

@ -0,0 +1,18 @@
type: object
required:
- role
properties:
role:
type: string
enum: ['agent', 'administrator']
description: Whether its administrator or agent
example: 'agent'
availability_status:
type: string
enum: ['available', 'busy', 'offline']
description: The availability status of the agent.
example: 'available'
auto_offline:
type: boolean
description: Whether the availability status of agent is configured to go offline automatically when away.
example: true

View File

@ -0,0 +1,30 @@
type: object
properties:
name:
type: string
description: The name of the agent bot
example: 'My Agent Bot'
description:
type: string
description: The description of the agent bot
example: 'This is a sample agent bot'
outgoing_url:
type: string
description: The webhook URL for the bot
example: 'https://example.com/webhook'
avatar:
type: string
format: binary
description: Send the form data with the avatar image binary or use the avatar_url
avatar_url:
type: string
description: The url to a jpeg, png file for the agent bot avatar
example: https://example.com/avatar.png
bot_type:
type: integer
description: The type of the bot (0 for webhook)
example: 0
bot_config:
type: object
description: The configuration for the bot
example: {}

View File

@ -0,0 +1,42 @@
type: object
properties:
name:
type: string
description: Rule name
example: Add label on message create event
description:
type: string
description: The description about the automation and actions
example: Add label support and sales on message create event if incoming message content contains text help
event_name:
type: string
enum:
- conversation_created
- conversation_updated
- conversation_resolved
- message_created
example: message_created
description: The event when you want to execute the automation actions
active:
type: boolean
description: Enable/disable automation rule
actions:
type: array
description: Array of actions which you want to perform when condition matches, e.g add label support if message contains content help.
items:
type: object
example:
action_name: add_label
action_params:
- support
conditions:
type: array
description: Array of conditions on which conversation filter would work, e.g message content contains text help.
items:
type: object
example:
attribute_key: content
filter_operator: contains
query_operator: OR
values:
- help

View File

@ -0,0 +1,10 @@
type: object
properties:
content:
type: string
description: Message content for canned response
example: 'Hello, {{contact.name}}! Welcome to our service.'
short_code:
type: string
description: Short Code for quick access of the canned response
example: 'welcome'

View File

@ -0,0 +1,44 @@
type: object
required:
- inbox_id
properties:
inbox_id:
type: number
description: ID of the inbox to which the contact belongs
example: 1
name:
type: string
description: name of the contact
example: Alice
email:
type: string
description: email of the contact
example: alice@acme.inc
blocked:
type: boolean
description: whether the contact is blocked or not
example: false
phone_number:
type: string
description: phone number of the contact
example: '+123456789'
avatar:
type: string
format: binary
description: Send the form data with the avatar image binary or use the avatar_url
avatar_url:
type: string
description: The url to a jpeg, png file for the contact avatar
example: https://example.com/avatar.png
identifier:
type: string
description: A unique identifier for the contact in external system
example: '1234567890'
additional_attributes:
type: object
description: An object where you can store additional attributes for contact. example {"type":"customer", "age":30}
example: { 'type': 'customer', 'age': 30 }
custom_attributes:
type: object
description: An object where you can store custom attributes for contact. example {"type":"customer", "age":30}, this should have a valid custom attribute definition.
example: {}

View File

@ -0,0 +1,38 @@
type: object
properties:
name:
type: string
description: name of the contact
example: Alice
email:
type: string
description: email of the contact
example: alice@acme.inc
blocked:
type: boolean
description: whether the contact is blocked or not
example: false
phone_number:
type: string
description: phone number of the contact
example: '+123456789'
avatar:
type: string
format: binary
description: Send the form data with the avatar image binary or use the avatar_url
avatar_url:
type: string
description: The url to a jpeg, png file for the contact avatar
example: https://example.com/avatar.png
identifier:
type: string
description: A unique identifier for the contact in external system
example: '1234567890'
additional_attributes:
type: object
description: An object where you can store additional attributes for contact. example {"type":"customer", "age":30}
example: { 'type': 'customer', 'age': 30 }
custom_attributes:
type: object
description: An object where you can store custom attributes for contact. example {"type":"customer", "age":30}, this should have a valid custom attribute definition.
example: {}

View File

@ -0,0 +1,93 @@
type: object
required:
- content
properties:
content:
type: string
description: The content of the message
example: 'Hello, how can I help you?'
message_type:
type: string
enum: ['outgoing', 'incoming']
description: The type of the message
example: 'outgoing'
private:
type: boolean
description: Flag to identify if it is a private note
example: false
content_type:
type: string
enum: ['text', 'input_email', 'cards', 'input_select', 'form', 'article']
description: Content type of the message
example: 'text'
content_attributes:
type: object
description: Attributes based on the content type
example: {}
campaign_id:
type: integer
description: The campaign id to which the message belongs
example: 1
template_params:
type: object
description: WhatsApp template parameters for sending structured messages
required:
- name
- category
- language
- processed_params
properties:
name:
type: string
description: Name of the WhatsApp template (must be approved in WhatsApp Business Manager)
example: 'purchase_receipt'
category:
type: string
enum: ['UTILITY', 'MARKETING', 'SHIPPING_UPDATE', 'TICKET_UPDATE', 'ISSUE_RESOLUTION']
description: Category of the template
example: 'UTILITY'
language:
type: string
description: Language code of the template (BCP 47 format)
example: 'en_US'
processed_params:
type: object
description: Processed template parameters organized by component type
properties:
body:
type: object
description: Body component parameters with variable placeholders
additionalProperties:
type: string
example:
'1': 'Visa'
'2': 'Nike'
'3': 'Bill'
header:
type: object
description: Header component parameters for media templates
properties:
media_url:
type: string
format: uri
description: Publicly accessible URL for IMAGE, VIDEO, or DOCUMENT headers
example: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
media_type:
type: string
enum: ['image', 'video', 'document']
description: Type of media for the header
example: 'document'
buttons:
type: array
description: Button component parameters for interactive templates
items:
type: object
properties:
type:
type: string
enum: ['url', 'copy_code']
description: Type of button parameter
parameter:
type: string
description: Dynamic parameter value for the button
example: 'SSFSDFSD'

View File

@ -0,0 +1,79 @@
type: object
required:
- source_id
- inbox_id
properties:
source_id:
type: string
description: Conversation source id
example: '1234567890'
inbox_id:
type: integer
description: 'Id of inbox in which the conversation is created <br/> Allowed Inbox Types: Website, Phone, Api, Email'
example: 1
contact_id:
type: integer
description: Contact Id for which conversation is created
example: 1
additional_attributes:
type: object
description: Lets you specify attributes like browser information
example:
{
browser: 'Chrome',
browser_version: '89.0.4389.82',
os: 'Windows',
os_version: '10',
}
custom_attributes:
type: object
description: The object to save custom attributes for conversation, accepts custom attributes key and value
example: { attribute_key: attribute_value, priority_conversation_number: 3 }
status:
type: string
enum: ['open', 'resolved', 'pending']
description: Specify the conversation whether it's pending, open, closed
example: open
assignee_id:
type: integer
description: Agent Id for assigning a conversation to an agent
example: 1
team_id:
type: integer
description: Team Id for assigning a conversation to a team\
example: 1
snoozed_until:
type: string
format: date-time
description: Snoozed until date time
example: '2030-07-21T17:32:28Z'
message:
type: object
description: The initial message to be sent to the conversation
required: ['content']
properties:
content:
type: string
description: The content of the message
example: 'Hello, how can I help you?'
template_params:
type: object
description: The template params for the message in case of whatsapp Channel
properties:
name:
type: string
description: Name of the template
example: 'sample_issue_resolution'
category:
type: string
description: Category of the template
example: UTILITY
language:
type: string
description: Language of the template
example: en_US
processed_params:
type: object
description: The processed param values for template variables in template
example:
1: 'Chatwoot'

View File

@ -0,0 +1,36 @@
type: object
properties:
attribute_display_name:
type: string
description: Attribute display name
example: 'Custom Attribute'
attribute_display_type:
type: integer
description: Attribute display type (text- 0, number- 1, currency- 2, percent- 3, link- 4, date- 5, list- 6, checkbox- 7)
example: 0
attribute_description:
type: string
description: Attribute description
example: 'This is a custom attribute'
attribute_key:
type: string
description: Attribute unique key value
example: 'custom_attribute'
attribute_values:
type: array
description: Attribute values
items:
type: string
example: ['value1', 'value2']
attribute_model:
type: integer
description: Attribute type(conversation_attribute- 0, contact_attribute- 1)
example: 0
regex_pattern:
type: string
description: Regex pattern (Only applicable for type- text). The regex pattern is used to validate the attribute value(s).
example: '^[a-zA-Z0-9]+$'
regex_cue:
type: string
description: Regex cue message (Only applicable for type- text). The cue message is shown when the regex pattern is not matched.
example: 'Please enter a valid value'

View File

@ -0,0 +1,15 @@
type: object
properties:
name:
type: string
description: The name of the custom filter
example: 'My Custom Filter'
type:
type: string
enum: ['conversation', 'contact', 'report']
description: The description about the custom filter
example: 'conversation'
query:
type: object
description: A query that needs to be saved as a custom filter
example: {}

View File

@ -0,0 +1,88 @@
type: object
properties:
name:
type: string
description: The name of the inbox
example: 'Support'
avatar:
type: string
format: binary
description: Image file for avatar
greeting_enabled:
type: boolean
description: Enable greeting message
example: true
greeting_message:
type: string
description: Greeting message to be displayed on the widget
example: Hello, how can I help you?
enable_email_collect:
type: boolean
description: Enable email collection
example: true
csat_survey_enabled:
type: boolean
description: Enable CSAT survey
example: true
enable_auto_assignment:
type: boolean
description: Enable Auto Assignment
example: true
working_hours_enabled:
type: boolean
description: Enable working hours
example: true
out_of_office_message:
type: string
description: Out of office message to be displayed on the widget
example: We are currently out of office. Please leave a message and we will get back to you.
timezone:
type: string
description: Timezone of the inbox
example: 'America/New_York'
allow_messages_after_resolved:
type: boolean
description: Allow messages after conversation is resolved
example: true
lock_to_single_conversation:
type: boolean
description: Lock to single conversation
example: true
portal_id:
type: integer
description: Id of the help center portal to attach to the inbox
example: 1
sender_name_type:
type: string
description: Sender name type for the inbox
enum: ['friendly', 'professional']
example: 'friendly'
business_name:
type: string
description: Business name for the inbox
example: 'My Business'
channel:
type: object
properties:
type:
type: string
description: Type of the channel
enum:
['web_widget', 'api', 'email', 'line', 'telegram', 'whatsapp', 'sms']
example: web_widget
website_url:
type: string
description: URL at which the widget will be loaded
example: 'https://example.com'
welcome_title:
type: string
description: Welcome title to be displayed on the widget
example: 'Welcome to our support'
welcome_tagline:
type: string
description: Welcome tagline to be displayed on the widget
example: 'We are here to help you'
widget_color:
type: string
description: A Hex-color string used to customize the widget
example: '#FF5733'

View File

@ -0,0 +1,82 @@
type: object
properties:
name:
type: string
description: The name of the inbox
example: 'Support'
avatar:
type: string
format: binary
description: Image file for avatar
greeting_enabled:
type: boolean
description: Enable greeting message
example: true
greeting_message:
type: string
description: Greeting message to be displayed on the widget
example: Hello, how can I help you?
enable_email_collect:
type: boolean
description: Enable email collection
example: true
csat_survey_enabled:
type: boolean
description: Enable CSAT survey
example: true
enable_auto_assignment:
type: boolean
description: Enable Auto Assignment
example: true
working_hours_enabled:
type: boolean
description: Enable working hours
example: true
out_of_office_message:
type: string
description: Out of office message to be displayed on the widget
example: We are currently out of office. Please leave a message and we will get back to you.
timezone:
type: string
description: Timezone of the inbox
example: 'America/New_York'
allow_messages_after_resolved:
type: boolean
description: Allow messages after conversation is resolved
example: true
lock_to_single_conversation:
type: boolean
description: Lock to single conversation
example: true
portal_id:
type: integer
description: Id of the help center portal to attach to the inbox
example: 1
sender_name_type:
type: string
description: Sender name type for the inbox
enum: ['friendly', 'professional']
example: 'friendly'
business_name:
type: string
description: Business name for the inbox
example: 'My Business'
channel:
type: object
properties:
website_url:
type: string
description: URL at which the widget will be loaded
example: 'https://example.com'
welcome_title:
type: string
description: Welcome title to be displayed on the widget
example: 'Welcome to our support'
welcome_tagline:
type: string
description: Welcome tagline to be displayed on the widget
example: 'We are here to help you'
widget_color:
type: string
description: A Hex-color string used to customize the widget
example: '#FF5733'

View File

@ -0,0 +1,18 @@
type: object
properties:
app_id:
type: integer
description: The ID of app for which integration hook is being created
example: 1
inbox_id:
type: integer
description: The inbox ID, if the hook is an inbox hook
example: 1
status:
type: integer
description: The status of the integration (0 for inactive, 1 for active)
example: 1
settings:
type: object
description: The settings required by the integration
example: {}

View File

@ -0,0 +1,10 @@
type: object
properties:
status:
type: integer
description: The status of the integration (0 for inactive, 1 for active)
example: 1
settings:
type: object
description: The settings required by the integration
example: {}

View File

@ -0,0 +1,26 @@
type: object
properties:
name:
type: string
description: The name of the agent bot
example: 'My Agent Bot'
description:
type: string
description: The description of the agent bot
example: 'This is a sample agent bot'
outgoing_url:
type: string
description: The webhook URL for the bot
example: 'https://example.com/webhook'
account_id:
type: integer
description: The account ID to associate the agent bot with
example: 1
avatar:
type: string
format: binary
description: Send the form data with the avatar image binary or use the avatar_url
avatar_url:
type: string
description: The url to a jpeg, png file for the agent bot avatar
example: https://example.com/avatar.png

View File

@ -0,0 +1,51 @@
type: object
properties:
title:
type: string
description: The title of the article
example: 'Article Title'
slug:
type: string
description: The slug of the article
example: 'article-title'
position:
type: integer
description: article position in category
example: 1
content:
type: string
description: The text content.
example: 'This is the content of the article'
description:
type: string
description: The description of the article
example: 'This is the description of the article'
category_id:
type: integer
description: The category id of the article
example: 1
author_id:
type: integer
description: The author agent id of the article
example: 1
associated_article_id:
type: integer
description: To associate similar articles to each other, e.g to provide the link for the reference.
example: 2
status:
type: integer
description: The status of the article. 0 for draft, 1 for published, 2 for archived
example: 1
locale:
type: string
description: The locale of the article
example: 'en'
meta:
type: object
description: Use for search
example:
{
tags: ['article_name'],
title: 'article title',
description: 'article description',
}

View File

@ -0,0 +1,34 @@
type: object
properties:
name:
type: string
description: The name of the category
example: 'Category Name'
description:
type: string
description: A description for the category
example: 'Category description'
position:
type: integer
description: Category position in the portal list to sort
example: 1
slug:
type: string
description: The category slug used in the URL
example: 'category-name'
locale:
type: string
description: The locale of the category
example: en
icon:
type: string
description: The icon of the category as a string (emoji)
example: '📚'
parent_category_id:
type: integer
description: To define parent category, e.g product documentation has multiple level features in sales category or in engineering category.
example: 1
associated_category_id:
type: integer
description: To associate similar categories to each other, e.g same category of product documentation in different languages
example: 2

View File

@ -0,0 +1,38 @@
type: object
properties:
color:
type: string
description: Header color for help-center in hex format
example: '#FFFFFF'
custom_domain:
type: string
description: Custom domain to display help center.
example: chatwoot.help
header_text:
type: string
description: Help center header
example: Handbook
homepage_link:
type: string
description: link to main dashboard
example: https://www.chatwoot.com/
name:
type: string
description: Name for the portal
example: Handbook
page_title:
type: string
description: Page title for the portal
example: Handbook
slug:
type: string
description: Slug for the portal to display in link
example: handbook
archived:
type: boolean
description: Status to check if portal is live
example: false
config:
type: object
description: Configuration about supporting locales
example: { allowed_locales: ['en', 'es'], default_locale: 'en' }

View File

@ -0,0 +1,30 @@
type: object
properties:
identifier:
type: string
description: External identifier of the contact
example: '1234567890'
identifier_hash:
type: string
description: Identifier hash prepared for HMAC authentication
example: 'e93275d4eba0e5679ad55f5360af00444e2a888df9b0afa3e8b691c3173725f9'
email:
type: string
description: Email of the contact
example: alice@acme.inc
name:
type: string
description: Name of the contact
example: Alice
phone_number:
type: string
description: Phone number of the contact
example: '+123456789'
avatar:
type: string
format: binary
description: Send the form data with the avatar image binary or use the avatar_url
custom_attributes:
type: object
description: Custom attributes of the customer
example: {}

View File

@ -0,0 +1,6 @@
type: object
properties:
custom_attributes:
type: object
description: Custom attributes of the conversation
example: {}

View File

@ -0,0 +1,10 @@
type: object
properties:
content:
type: string
description: Content for the message
example: 'Hello, how can I help you?'
echo_id:
type: string
description: Temporary identifier which will be passed back via websockets
example: '1234567890'

View File

@ -0,0 +1,30 @@
type: object
properties:
submitted_values:
type: object
description: Replies to the Bot Message Types
properties:
name:
type: string
description: The name of the submiitted value
example: 'My Name'
title:
type: string
description: The title of the submitted value
example: 'My Title'
value:
type: string
description: The value of the submitted value
example: 'value'
csat_survey_response:
type: object
description: The CSAT survey response
properties:
feedback_message:
type: string
description: The feedback message of the CSAT survey response
example: 'Great service!'
rating:
type: integer
description: The rating of the CSAT survey response
example: 5

View File

@ -0,0 +1,14 @@
type: object
properties:
name:
type: string
description: The name of the team
example: Support Team
description:
type: string
description: The description of the team
example: This is a team of support agents
allow_auto_assign:
type: boolean
description: If this setting is turned on, the system would automatically assign the conversation to an agent in the team while assigning the conversation to a team
example: true

View File

@ -0,0 +1,22 @@
type: object
properties:
name:
type: string
description: Name of the user
example: 'Daniel'
display_name:
type: string
description: Display name of the user
example: 'Dan'
email:
type: string
description: Email of the user
example: 'daniel@acme.inc'
password:
type: string
description: Password must contain uppercase, lowercase letters, number and a special character
example: 'Password2!'
custom_attributes:
type: object
description: Custom attributes you want to associate with the user
example: {}

View File

@ -0,0 +1,28 @@
type: object
properties:
url:
type: string
description: The url where the events should be sent
example: https://example.com/webhook
name:
type: string
description: The name of the webhook
subscriptions:
type: array
items:
type: string
enum:
[
'conversation_created',
'conversation_status_changed',
'conversation_updated',
'message_created',
'message_updated',
'contact_created',
'contact_updated',
'webwidget_triggered',
]
description: The events you want to subscribe to.
example:
- conversation_created
- conversation_status_changed

View File

@ -0,0 +1,12 @@
type: object
properties:
id:
type: number
description: Account ID
name:
type: string
description: Name of the account
role:
type: string
enum: ['administrator', 'agent']
description: The user role in the account

View File

@ -0,0 +1,84 @@
type: object
properties:
id:
type: number
description: Account ID
name:
type: string
description: Name of the account
locale:
type: string
description: The locale of the account
domain:
type: string
description: The domain of the account
support_email:
type: string
description: The support email of the account
status:
type: string
description: The status of the account
created_at:
type: string
format: date-time
description: The creation date of the account
cache_keys:
type: object
description: Cache keys for the account
features:
type: array
items:
type: string
description: Enabled features for the account
settings:
type: object
description: Account settings
properties:
auto_resolve_after:
type: number
description: Auto resolve conversations after specified minutes
auto_resolve_message:
type: string
description: Message to send when auto resolving
auto_resolve_ignore_waiting:
type: boolean
description: Whether to ignore waiting conversations for auto resolve
custom_attributes:
type: object
description: Custom attributes of the account
properties:
plan_name:
type: string
description: Subscription plan name
subscribed_quantity:
type: number
description: Subscribed quantity
subscription_status:
type: string
description: Subscription status
subscription_ends_on:
type: string
format: date
description: Subscription end date
industry:
type: string
description: Industry type
company_size:
type: string
description: Company size
timezone:
type: string
description: Account timezone
logo:
type: string
description: Account logo URL
onboarding_step:
type: string
description: Current onboarding step
marked_for_deletion_at:
type: string
format: date-time
description: When account was marked for deletion
marked_for_deletion_reason:
type: string
description: Reason for account deletion

View File

@ -0,0 +1,13 @@
allOf:
- $ref: '#/components/schemas/account_detail'
- type: object
properties:
latest_chatwoot_version:
type: string
description: Latest version of Chatwoot available
example: "3.0.0"
subscribed_features:
type: array
items:
type: string
description: List of subscribed enterprise features (if enterprise edition is enabled)

View File

@ -0,0 +1,14 @@
type: array
description: 'Array of account users'
items:
type: object
properties:
account_id:
type: integer
description: The ID of the account
user_id:
type: integer
description: The ID of the user
role:
type: string
description: whether user is an administrator or agent

View File

@ -0,0 +1,35 @@
type: object
properties:
id:
type: integer
account_id:
type: integer
availability_status:
type: string
enum: ['available', 'busy', 'offline']
description: The availability status of the agent computed by Chatwoot.
auto_offline:
type: boolean
description: Whether the availability status of agent is configured to go offline automatically when away.
confirmed:
type: boolean
description: Whether the agent has confirmed their email address.
email:
type: string
description: The email of the agent
available_name:
type: string
description: The available name of the agent
name:
type: string
description: The name of the agent
role:
type: string
enum: ['agent', 'administrator']
description: The role of the agent
thumbnail:
type: string
description: The thumbnail of the agent
custom_role_id:
type: integer
description: The custom role id of the agent

View File

@ -0,0 +1,32 @@
type: object
properties:
id:
type: number
description: ID of the agent bot
name:
type: string
description: The name of the agent bot
description:
type: string
description: The description about the agent bot
thumbnail:
type: string
description: The thumbnail of the agent bot
outgoing_url:
type: string
description: The webhook URL for the bot
bot_type:
type: string
description: The type of the bot
bot_config:
type: object
description: The configuration of the bot
account_id:
type: number
description: Account ID if it's an account specific bot
access_token:
type: string
description: The access token for the bot
system_bot:
type: boolean
description: Whether the bot is a system bot

View File

@ -0,0 +1,33 @@
type: object
properties:
id:
type: integer
content:
type: string
description: The text content.
meta:
type: object
position:
type: integer
status:
type: integer
enum: ['draft', 'published', 'archived']
title:
type: string
slug:
type: string
views:
type: integer
portal_id:
type: integer
account_id:
type: integer
author_id:
type: integer
category_id:
type: integer
folder_id:
type: integer
associated_article_id:
type: integer
description: To associate similar articles to each other, e.g to provide the link for the reference.

View File

@ -0,0 +1,53 @@
type: object
properties:
id:
type: integer
description: Unique identifier for the audit log entry
auditable_id:
type: integer
description: The ID of the audited object
auditable_type:
type: string
description: The type of the audited object (e.g., Conversation, Contact, User)
auditable:
type: object
description: The audited object data
associated_id:
type: integer
description: The ID of the associated object (typically the account ID)
associated_type:
type: string
description: The type of the associated object
user_id:
type: integer
description: The ID of the user who performed the action
user_type:
type: string
description: The type of user who performed the action
username:
type: string
description: The email/username of the user who performed the action
action:
type: string
enum: ['create', 'update', 'destroy']
description: The action performed on the object
audited_changes:
type: object
description: JSON object containing the changes made to the audited object
version:
type: integer
description: Version number of the audit log entry
comment:
type: string
nullable: true
description: Optional comment associated with the audit log entry
request_uuid:
type: string
description: UUID to identify the request that generated this audit log
created_at:
type: integer
description: Unix timestamp when the audit log entry was created
remote_address:
type: string
nullable: true
description: IP address from which the action was performed

View File

@ -0,0 +1,13 @@
type: object
properties:
payload:
description: Response payload that contains automation rule(s)
oneOf:
- type: array
description: Array of automation rules (for listing endpoint)
items:
$ref: '#/components/schemas/automation_rule_item'
- type: object
description: Single automation rule (for show/create/update endpoints)
allOf:
- $ref: '#/components/schemas/automation_rule_item'

View File

@ -0,0 +1,69 @@
type: object
properties:
id:
type: integer
description: The ID of the automation rule
account_id:
type: integer
description: Account Id
name:
type: string
description: The name of the rule
example: Add label on message create event
description:
type: string
description: Description to give more context about the rule
example: Add label support and sales on message create event if incoming message content contains text help
event_name:
type: string
description: Automation Rule event, on which we call the actions(conversation_created, conversation_updated, message_created)
enum:
- conversation_created
- conversation_updated
- message_created
example: message_created
conditions:
type: array
description: Array of conditions on which conversation/message filter would work
items:
type: object
properties:
values:
type: array
items:
type: string
attribute_key:
type: string
query_operator:
type: string
filter_operator:
type: string
example:
attribute_key: content
filter_operator: contains
values:
- help
query_operator: and
actions:
type: array
description: Array of actions which we perform when condition matches
items:
type: object
properties:
action_name:
type: string
action_params:
type: array
items:
type: string
example:
action_name: add_label
action_params:
- support
- sales
created_on:
type: integer
description: The timestamp when the rule was created
active:
type: boolean
description: Enable/disable automation rule

View File

@ -0,0 +1,20 @@
type: object
properties:
id:
type: integer
description: ID of the canned response
account_id:
type: integer
description: Account Id
short_code:
type: string
description: Short Code for quick access of the canned response
content:
type: string
description: Message content for canned response
created_at:
type: string
description: The date and time when the canned response was created
updated_at:
type: string
description: The date and time when the canned response was updated

View File

@ -0,0 +1,25 @@
type: object
properties:
id:
type: integer
description:
type: string
description: The text content.
locale:
type: string
name:
type: string
slug:
type: string
position:
type: integer
portal_id:
type: integer
account_id:
type: integer
associated_category_id:
type: integer
description: To associate similar categories to each other, e.g same category of product documentation in different languages
parent_category_id:
type: integer
description: To define parent category, e.g product documentation has multiple level features in sales category or in engineering category.

View File

@ -0,0 +1,49 @@
type: object
properties:
payload:
type: array
items:
type: object
properties:
additional_attributes:
type: object
description: The object containing additional attributes related to the contact
availability_status:
type: string
description: The availability status of the contact
email:
type: string
description: The email address of the contact
id:
type: integer
description: The ID of the contact
name:
type: string
description: The name of the contact
phone_number:
type: string
description: The phone number of the contact
blocked:
type: boolean
description: Whether the contact is blocked
identifier:
type: string
description: The identifier of the contact
thumbnail:
type: string
description: The thumbnail of the contact
custom_attributes:
type: object
description: The custom attributes of the contact
example:
{ attribute_key: attribute_value, signed_up_at: dd/mm/yyyy }
last_activity_at:
type: integer
description: The last activity at of the contact
created_at:
type: integer
description: The created at of the contact
contact_inboxes:
type: array
items:
$ref: '#/components/schemas/contact_inboxes'

View File

@ -0,0 +1,109 @@
type: object
properties:
id:
type: integer
description: ID of the message
content:
type: string
description: Content of the message
account_id:
type: integer
description: ID of the account
inbox_id:
type: integer
description: ID of the inbox
conversation_id:
type: integer
description: ID of the conversation
message_type:
type: integer
description: Type of the message
created_at:
type: integer
description: Timestamp when message was created
updated_at:
type: string
description: Formatted datetime when message was updated
private:
type: boolean
description: Whether the message is private
status:
type: string
description: Status of the message
source_id:
type: string
description: Source ID of the message
nullable: true
content_type:
type: string
description: Type of the content
content_attributes:
type: object
description: Attributes of the content
sender_type:
type: string
description: Type of the sender
nullable: true
sender_id:
type: integer
description: ID of the sender
nullable: true
external_source_ids:
type: object
description: External source IDs
additional_attributes:
type: object
description: Additional attributes of the message
processed_message_content:
type: string
description: Processed message content
nullable: true
sentiment:
type: object
description: Sentiment analysis of the message
conversation:
type: object
description: Conversation details
properties:
assignee_id:
type: integer
description: ID of the assignee
nullable: true
unread_count:
type: integer
description: Count of unread messages
last_activity_at:
type: integer
description: Timestamp of last activity
contact_inbox:
type: object
description: Contact inbox details
properties:
source_id:
type: string
description: Source ID of the contact inbox
sender:
type: object
description: Details of the sender
properties:
id:
type: integer
description: ID of the sender
name:
type: string
description: Name of the sender
available_name:
type: string
description: Available name of the sender
avatar_url:
type: string
description: URL of the sender's avatar
type:
type: string
description: Type of the sender
availability_status:
type: string
description: Availability status of the sender
thumbnail:
type: string
description: Thumbnail URL of the sender

View File

@ -0,0 +1,13 @@
type: object
properties:
payload:
type: array
items:
allOf:
- $ref: '#/components/schemas/conversation'
- type: object
properties:
meta:
$ref: './extension/contact/conversation.yml#/properties/meta'
description: Meta information about the conversation
description: List of conversations for the contact

View File

@ -0,0 +1,48 @@
type: object
properties:
additional_attributes:
type: object
description: The object containing additional attributes related to the contact
properties:
city:
type: string
description: City of the contact
country:
type: string
description: Country of the contact
country_code:
type: string
description: Country code of the contact
created_at_ip:
type: string
description: IP address when the contact was created
custom_attributes:
type: object
description: The custom attributes of the contact
email:
type: string
description: The email address of the contact
id:
type: integer
description: The ID of the contact
identifier:
type: string
description: The identifier of the contact
nullable: true
name:
type: string
description: The name of the contact
phone_number:
type: string
description: The phone number of the contact
nullable: true
thumbnail:
type: string
description: The thumbnail of the contact
blocked:
type: boolean
description: Whether the contact is blocked
type:
type: string
description: The type of entity
enum: ["contact"]

View File

@ -0,0 +1,27 @@
type: object
properties:
source_id:
type: string
description: Source identifier for the contact inbox
inbox:
type: object
properties:
id:
type: integer
description: ID of the inbox
avatar_url:
type: string
description: URL for the inbox avatar
channel_id:
type: integer
description: ID of the channel
name:
type: string
description: Name of the inbox
channel_type:
type: string
description: Type of channel
provider:
type: string
description: Provider of the inbox
nullable: true

View File

@ -0,0 +1,7 @@
type: object
properties:
source_id:
type: string
description: Contact Inbox Source Id
inbox:
$ref: '#/components/schemas/inbox_contact'

View File

@ -0,0 +1,61 @@
type: object
properties:
additional_attributes:
type: object
description: The object containing additional attributes related to the contact
properties:
city:
type: string
description: City of the contact
country:
type: string
description: Country of the contact
country_code:
type: string
description: Country code of the contact
created_at_ip:
type: string
description: IP address when the contact was created
availability_status:
type: string
description: Availability status of the contact
enum: ["online", "offline"]
email:
type: string
description: The email address of the contact
nullable: true
id:
type: integer
description: The ID of the contact
name:
type: string
description: The name of the contact
phone_number:
type: string
description: The phone number of the contact
nullable: true
blocked:
type: boolean
description: Whether the contact is blocked
identifier:
type: string
description: The identifier of the contact
nullable: true
thumbnail:
type: string
description: The thumbnail of the contact
custom_attributes:
type: object
description: The custom attributes of the contact
last_activity_at:
type: integer
description: Timestamp of last activity
nullable: true
created_at:
type: integer
description: Timestamp when contact was created
contact_inboxes:
type: array
description: List of inboxes associated with this contact
items:
$ref: '#/components/schemas/contact_inbox'

View File

@ -0,0 +1,8 @@
type: object
properties:
count:
type: integer
description: Total number of contacts
current_page:
type: string
description: Current page number

View File

@ -0,0 +1,5 @@
type: object
properties:
payload:
$ref: '#/components/schemas/contact_list_item'
description: Contact details

View File

@ -0,0 +1,8 @@
type: object
properties:
source_id:
type: string
description: Contact Inbox Source Id
inbox:
type: object
$ref: '#/components/schemas/inbox'

View File

@ -0,0 +1,7 @@
type: object
properties:
payload:
type: array
items:
$ref: '#/components/schemas/contact_inbox'
description: List of contactable inboxes for the contact

View File

@ -0,0 +1,10 @@
type: object
properties:
meta:
$ref: '#/components/schemas/contact_meta'
description: Metadata about the contact list response
payload:
type: array
items:
$ref: '#/components/schemas/contact_list_item'
description: List of contacts

View File

@ -0,0 +1,91 @@
type: object
properties:
id:
type: number
description: ID of the conversation
messages:
type: array
items:
$ref: '#/components/schemas/message'
account_id:
type: number
description: Account Id
uuid:
type: string
description: UUID of the conversation
additional_attributes:
type: object
description: The object containing additional attributes related to the conversation
agent_last_seen_at:
type: number
description: The last activity at of the agent
assignee_last_seen_at:
type: number
description: The last activity at of the assignee
can_reply:
type: boolean
description: Whether the conversation can be replied to
contact_last_seen_at:
type: number
description: The last activity at of the contact
custom_attributes:
type: object
description: The object to save custom attributes for conversation, accepts custom attributes key and value
inbox_id:
type: number
description: ID of the inbox
labels:
type: array
items:
type: string
description: The labels of the conversation
muted:
type: boolean
description: Whether the conversation is muted
snoozed_until:
type: number
description: The time at which the conversation will be unmuted
status:
type: string
enum: ['open', 'resolved', 'pending']
description: The status of the conversation
created_at:
type: number
description: The time at which conversation was created
updated_at:
type: number
description: The time at which conversation was updated
timestamp:
type: string
description: The time at which conversation was created
first_reply_created_at:
type: number
description: The time at which the first reply was created
unread_count:
type: number
description: The number of unread messages
last_non_activity_message:
type: object
$ref: '#/components/schemas/message'
description: The last non activity message
last_activity_at:
type: number
description: The last activity at of the conversation
priority:
type: string
description: The priority of the conversation
waiting_since:
type: number
description: The time at which the conversation was waiting
sla_policy_id:
type: number
description: The ID of the SLA policy
applied_sla:
type: object
description: The applied SLA
sla_events:
type: array
items:
type: object
description: SLA event objects

View File

@ -0,0 +1,10 @@
type: object
properties:
meta:
$ref: '#/components/schemas/conversation_meta'
description: Meta information about the conversation
payload:
type: array
items:
$ref: '#/components/schemas/message_detailed'
description: List of messages in the conversation

View File

@ -0,0 +1,55 @@
type: object
properties:
labels:
type: array
items:
type: string
description: Labels associated with the conversation
additional_attributes:
type: object
properties:
browser:
type: object
properties:
device_name:
type: string
description: Name of the device
browser_name:
type: string
description: Name of the browser
platform_name:
type: string
description: Name of the platform
browser_version:
type: string
description: Version of the browser
platform_version:
type: string
description: Version of the platform
referer:
type: string
description: Referrer URL
initiated_at:
type: object
properties:
timestamp:
type: string
description: Timestamp when the conversation was initiated
browser_language:
type: string
description: Browser language setting
conversation_language:
type: string
description: Conversation language
description: Additional attributes of the conversation
contact:
$ref: '#/components/schemas/contact_detail'
description: Contact details
agent_last_seen_at:
type: string
description: Timestamp when the agent last saw the conversation
nullable: true
assignee_last_seen_at:
type: string
description: Timestamp when the assignee last saw the conversation
nullable: true

View File

@ -0,0 +1,38 @@
type: object
properties:
id:
type: integer
description: Identifier
attribute_display_name:
type: string
description: Attribute display name
attribute_display_type:
type: string
description: Attribute display type (text, number, currency, percent, link, date, list, checkbox)
attribute_description:
type: string
description: Attribute description
attribute_key:
type: string
description: Attribute unique key value
regex_pattern:
type: string
description: Regex pattern
regex_cue:
type: string
description: Regex cue
attribute_values:
type: string
description: Attribute values
attribute_model:
type: string
description: Attribute type(conversation_attribute/contact_attribute)
default_value:
type: string
description: Attribute default value
created_at:
type: string
description: The date and time when the custom attribute was created
updated_at:
type: string
description: The date and time when the custom attribute was updated

View File

@ -0,0 +1,23 @@
type: object
properties:
id:
type: number
description: The ID of the custom filter
name:
type: string
description: The name of the custom filter
type:
type: string
enum: ["conversation", "contact", "report"]
description: The description about the custom filter
query:
type: object
description: A query that needs to be saved as a custom filter
created_at:
type: string
format: date-time
description: The time at which the custom filter was created
updated_at:
type: string
format: date-time
description: The time at which the custom filter was updated

View File

@ -0,0 +1,53 @@
type: object
properties:
meta:
type: object
properties:
sender:
type: object
properties:
additional_attributes:
type: object
description: The additional attributes of the sender
availability_status:
type: string
description: The availability status of the sender
email:
type: string
description: The email of the sender
id:
type: number
description: ID fo the sender
name:
type: string
description: The name of the sender
phone_number:
type: string
description: The phone number of the sender
blocked:
type: boolean
description: Whether the sender is blocked
identifier:
type: string
description: The identifier of the sender
thumbnail:
type: string
description: Avatar URL of the contact
custom_attributes:
type: object
description: The custom attributes of the sender
last_activity_at:
type: number
description: The last activity at of the sender
created_at:
type: number
description: The created at of the sender
channel:
type: string
description: Channel Type
assignee:
$ref: '#/components/schemas/user'
hmac_verified:
type: boolean
description: Whether the hmac is verified

View File

@ -0,0 +1,7 @@
type: object
properties:
payload:
type: array
description: Array of labels
items:
type: string

View File

@ -0,0 +1,9 @@
type: object
properties:
id:
type: number
description: Id of the user
availability_status:
type: string
enum: ['online', 'offline']
description: Availability status of the user

View File

@ -0,0 +1,7 @@
type: object
properties:
payload:
type: array
description: Array of labels
items:
type: string

View File

@ -0,0 +1,24 @@
type: object
properties:
data:
type: object
properties:
meta:
type: object
properties:
mine_count:
type: number
unassigned_count:
type: number
assigned_count:
type: number
all_count:
type: number
payload:
type: array
description: 'array of conversations'
items:
allOf:
- $ref: '#/components/schemas/generic_id'
- $ref: '#/components/schemas/conversation'
- $ref: '../contact/conversation.yml'

View File

@ -0,0 +1,4 @@
type: object
allOf:
- $ref: '#/components/schemas/conversation'
- $ref: '../contact/conversation.yml'

View File

@ -0,0 +1,14 @@
type: object
properties:
meta:
type: object
payload:
type: object
properties:
success:
type: boolean
current_status:
type: string
enum: ['open', 'resolved']
conversation_id:
type: number

View File

@ -0,0 +1,4 @@
type: object
properties:
display_id:
type: number

View File

@ -0,0 +1,4 @@
type: object
properties:
id:
type: number

View File

@ -0,0 +1,4 @@
type: object
properties:
source_id:
type: number

View File

@ -0,0 +1,125 @@
type: object
properties:
id:
type: number
description: ID of the inbox
name:
type: string
description: The name of the inbox
website_url:
type: string
description: Website URL
channel_type:
type: string
description: The type of the inbox
avatar_url:
type: string
description: The avatar image of the inbox
widget_color:
type: string
description: Widget Color used for customization of the widget
website_token:
type: string
description: Website Token
enable_auto_assignment:
type: boolean
description: The flag which shows whether Auto Assignment is enabled or not
web_widget_script:
type: string
description: Script used to load the website widget
welcome_title:
type: string
description: Welcome title to be displayed on the widget
welcome_tagline:
type: string
description: Welcome tagline to be displayed on the widget
greeting_enabled:
type: boolean
description: The flag which shows whether greeting is enabled
greeting_message:
type: string
description: A greeting message when the user starts the conversation
channel_id:
type: number
description: ID of the channel this inbox belongs to
working_hours_enabled:
type: boolean
description: The flag which shows whether working hours feature is enabled
enable_email_collect:
type: boolean
description: The flag to enable collecting email from contacts
csat_survey_enabled:
type: boolean
description: The flag to enable CSAT survey
auto_assignment_config:
type: object
description: Configuration settings for auto assignment
out_of_office_message:
type: string
description: Message to show when agents are out of office
working_hours:
type: array
description: Configuration for working hours of the inbox
items:
type: object
properties:
day_of_week:
type: number
description: Day of the week (0-6, where 0 is Sunday)
closed_all_day:
type: boolean
description: Whether the inbox is closed for the entire day
open_hour:
type: number
description: Hour when inbox opens (0-23)
open_minutes:
type: number
description: Minutes of the hour when inbox opens (0-59)
close_hour:
type: number
description: Hour when inbox closes (0-23)
close_minutes:
type: number
description: Minutes of the hour when inbox closes (0-59)
open_all_day:
type: boolean
description: Whether the inbox is open for the entire day
timezone:
type: string
description: Timezone configuration for the inbox
callback_webhook_url:
type: string
description: Webhook URL for callbacks
allow_messages_after_resolved:
type: boolean
description: Whether to allow messages after a conversation is resolved
lock_to_single_conversation:
type: boolean
description: Whether to lock a contact to a single conversation
sender_name_type:
type: string
description: Type of sender name to display (e.g., friendly)
business_name:
type: string
description: Business name associated with the inbox
hmac_mandatory:
type: boolean
description: Whether HMAC verification is mandatory
selected_feature_flags:
type: object
description: Selected feature flags for the inbox
reply_time:
type: string
description: Expected reply time
messaging_service_sid:
type: string
description: Messaging service SID for SMS providers
phone_number:
type: string
description: Phone number associated with the inbox
medium:
type: string
description: Medium of communication (e.g., sms, email)
provider:
type: string
description: Provider of the channel

View File

@ -0,0 +1,20 @@
type: object
properties:
id:
type: number
description: ID of the inbox
avatar_url:
type: string
description: The avatar image of the inbox
channel_id:
type: number
description: The ID of the channel
name:
type: string
description: The name of the inbox
channel_type:
type: string
description: The type of the inbox
provider:
type: string
description: The provider of the inbox

View File

@ -0,0 +1,25 @@
type: object
properties:
id:
type: string
description: The ID of the integration
name:
type: string
description: The name of the integration
description:
type: string
description: The description about the team
hook_type:
type: string
description: Whether the integration is an account or inbox integration
enabled:
type: boolean
description: Whether the integration is enabled for the account
allow_multiple_hooks:
type: boolean
description: Whether multiple hooks can be created for the integration
hooks:
type: array
items:
type: object
description: If there are any hooks created for this integration

View File

@ -0,0 +1,23 @@
type: object
properties:
id:
type: string
description: The ID of the integration hook
app_id:
type: string
description: The ID of the integration app
inbox_id:
type: string
description: Inbox ID if its an Inbox integration
account_id:
type: string
description: Account ID of the integration
status:
type: boolean
description: Whether the integration hook is enabled for the account
hook_type:
type: boolean
description: Whether its an account or inbox integration hook
settings:
type: object
description: The associated settings for the integration

View File

@ -0,0 +1,72 @@
type: object
properties:
id:
type: number
description: The ID of the message
content:
type: string
description: The text content of the message
account_id:
type: number
description: The ID of the account
inbox_id:
type: number
description: The ID of the inbox
conversation_id:
type: number
description: The ID of the conversation
message_type:
type: integer
enum: [0, 1, 2]
description: The type of the message
created_at:
type: integer
description: The time at which message was created
updated_at:
type: integer
description: The time at which message was updated
private:
type: boolean
description: The flags which shows whether the message is private or not
status:
type: string
enum: ["sent", "delivered", "read", "failed"]
description: The status of the message
source_id:
type: string
description: The source ID of the message
content_type:
type: string
enum: ["text", "input_select", "cards", "form"]
description: The type of the template message
content_attributes:
type: object
description: The content attributes for each content_type
sender_type:
type: string
enum: ["contact", "agent", "agent_bot"]
description: The type of the sender
sender_id:
type: number
description: The ID of the sender
external_source_ids:
type: object
description: The external source IDs of the message
additional_attributes:
type: object
description: The additional attributes of the message
processed_message_content:
type: string
description: The processed message content
sentiment:
type: object
description: The sentiment of the message
conversation:
type: object
description: The conversation object
attachment:
type: object
description: The file object attached to the image
sender:
type: object
description: User/Agent/AgentBot object

View File

@ -0,0 +1,47 @@
type: object
properties:
id:
type: number
description: The ID of the message
content:
type: string
description: The text content of the message
inbox_id:
type: number
description: The ID of the inbox
conversation_id:
type: number
description: The ID of the conversation
message_type:
type: integer
enum: [0, 1, 2, 3]
description: "The type of the message (0: incoming, 1: outgoing, 2: activity, 3: template)"
content_type:
type: string
enum: ["text", "input_select", "cards", "form", "input_csat"]
description: The type of the message content
status:
type: string
enum: ["sent", "delivered", "read", "failed"]
description: The status of the message
content_attributes:
type: object
description: The content attributes for each content_type
properties:
in_reply_to:
type: string
description: ID of the message this is replying to
nullable: true
created_at:
type: integer
description: The timestamp when message was created
private:
type: boolean
description: The flag which shows whether the message is private or not
source_id:
type: string
description: The source ID of the message
nullable: true
sender:
$ref: '#/components/schemas/contact_detail'
description: The sender of the message (only for incoming messages)

View File

@ -0,0 +1,9 @@
type: object
properties:
id:
type: number
description: Account ID
name:
type: string
description: Name of the account

View File

@ -0,0 +1,6 @@
type: object
properties:
payload:
type: array
items:
$ref: '#/components/schemas/portal_item'

View File

@ -0,0 +1,18 @@
type: object
description: Configuration settings for the portal
properties:
allowed_locales:
type: array
description: List of allowed locales for the portal
items:
type: object
properties:
code:
type: string
description: The language code
articles_count:
type: integer
description: Number of articles in this locale
categories_count:
type: integer
description: Number of categories in this locale

View File

@ -0,0 +1,40 @@
type: object
properties:
id:
type: integer
description: The ID of the portal
archived:
type: boolean
description: Whether the portal is archived
color:
type: string
description: The color code for the portal
config:
$ref: '#/components/schemas/portal_config'
custom_domain:
type: string
description: Custom domain for the portal
header_text:
type: string
description: The header text for the portal
homepage_link:
type: string
description: Homepage link for the portal
name:
type: string
description: Name of the portal
slug:
type: string
description: URL slug for the portal
page_title:
type: string
description: Page title for the portal
account_id:
type: integer
description: ID of the account the portal belongs to
inbox:
$ref: '#/components/schemas/inbox'
logo:
$ref: '#/components/schemas/portal_logo'
meta:
$ref: '#/components/schemas/portal_meta'

View File

@ -0,0 +1,23 @@
type: object
properties:
id:
type: integer
description: ID of the logo file
portal_id:
type: integer
description: ID of the portal this logo belongs to
file_type:
type: string
description: MIME type of the file
account_id:
type: integer
description: ID of the account
file_url:
type: string
description: URL to access the logo file
blob_id:
type: integer
description: ID of the blob
filename:
type: string
description: Name of the file

View File

@ -0,0 +1,23 @@
type: object
properties:
all_articles_count:
type: integer
description: Total number of articles
archived_articles_count:
type: integer
nullable: true
description: Number of archived articles
published_count:
type: integer
nullable: true
description: Number of published articles
draft_articles_count:
type: integer
nullable: true
description: Number of draft articles
categories_count:
type: integer
description: Number of categories
default_locale:
type: string
description: Default locale for the portal

View File

@ -0,0 +1,5 @@
type: object
properties:
payload:
description: A single portal object (for show/update endpoints)
$ref: '#/components/schemas/portal_item'

View File

@ -0,0 +1,17 @@
type: object
properties:
id:
type: integer
description: Id of the contact
source_id:
type: string
description: The session identifier of the contact
name:
type: string
description: Name of the contact
email:
type: string
description: Email of the contact
pubsub_token:
type: string
description: The token to be used to connect to chatwoot websocket

View File

@ -0,0 +1,16 @@
type: object
properties:
id:
type: integer
description: Id of the conversation
inbox_id:
type: string
description: The inbox id of the conversation
messages:
type: array
items:
$ref: '#/components/schemas/message'
description: Messages in the conversation
contact:
type: object
description: The contact information associated to the conversation

View File

@ -0,0 +1,50 @@
type: object
properties:
identifier:
type: string
description: Inbox identifier
name:
type: string
description: Name of the inbox
timezone:
type: string
description: The timezone defined on the inbox
working_hours:
type: array
description: The working hours defined on the inbox
items:
type: object
properties:
day_of_week:
type: integer
description: Day of the week as a number. Sunday -> 0, Saturday -> 6
open_all_day:
type: boolean
description: Whether or not the business is open the whole day
closed_all_day:
type: boolean
description: Whether or not the business is closed the whole day
open_hour:
type: integer
description: Opening hour. Can be null if closed all day
open_minutes:
type: integer
description: Opening minute. Can be null if closed all day
close_hour:
type: integer
description: Closing hour. Can be null if closed all day
close_minutes:
type: integer
description: Closing minute. Can be null if closed all day
working_hours_enabled:
type: boolean
description: Whether of not the working hours are enabled on the inbox
csat_survey_enabled:
type: boolean
description: Whether of not the Customer Satisfaction survey is enabled on the inbox
greeting_enabled:
type: boolean
description: Whether of not the Greeting Message is enabled on the inbox
identity_validation_enabled:
type: boolean
description: Whether of not the User Identity Validation is enforced on the inbox

View File

@ -0,0 +1,38 @@
type: object
properties:
id:
type: string
description: Id of the message
content:
type: string
description: Text content of the message
message_type:
type: string
description: Denotes the message type
content_type:
type: string
description: Content type of the message
content_attributes:
type: string
description: Additional content attributes of the message
created_at:
type: string
description: Created at time stamp of the message
conversation_id:
type: string
description: Conversation Id of the message
attachments:
type: array
items:
type: object
description: Attachments if any
sender:
type: object
description: Details of the sender

View File

@ -0,0 +1,47 @@
type: object
properties:
id:
type: number
description: ID of the reporting event
name:
type: string
description: Name of the event (e.g., first_response, resolution, reply_time)
value:
type: number
format: double
description: Value of the metric in seconds
value_in_business_hours:
type: number
format: double
description: Value of the metric in seconds, calculated only for business hours
event_start_time:
type: string
format: date-time
description: The timestamp when the event started
event_end_time:
type: string
format: date-time
description: The timestamp when the event ended
account_id:
type: number
description: ID of the account
conversation_id:
type: number
nullable: true
description: ID of the conversation
inbox_id:
type: number
nullable: true
description: ID of the inbox
user_id:
type: number
nullable: true
description: ID of the user/agent
created_at:
type: string
format: date-time
description: The timestamp when the reporting event was created
updated_at:
type: string
format: date-time
description: The timestamp when the reporting event was last updated

View File

@ -0,0 +1,11 @@
type: object
properties:
count:
type: integer
description: Total number of reporting events
current_page:
type: integer
description: Current page number
total_pages:
type: integer
description: Total number of pages

View File

@ -0,0 +1,10 @@
type: object
properties:
meta:
$ref: '#/components/schemas/reporting_event_meta'
description: Metadata about the reporting events list response
payload:
type: array
items:
$ref: '#/components/schemas/reporting_event'
description: List of reporting events

View File

@ -0,0 +1,19 @@
type: object
properties:
id:
type: number
name:
type: string
email:
type: string
thumbnail:
type: string
availability:
type: string
metric:
type: object
properties:
open:
type: number
unattended:
type: number

View File

@ -0,0 +1,29 @@
type: object
properties:
avg_first_response_time:
type: string
avg_resolution_time:
type: string
conversations_count:
type: number
incoming_messages_count:
type: number
outgoing_messages_count:
type: number
resolutions_count:
type: number
previous:
type: object
properties:
avg_first_response_time:
type: string
avg_resolution_time:
type: string
conversations_count:
type: number
incoming_messages_count:
type: number
outgoing_messages_count:
type: number
resolutions_count:
type: number

View File

@ -0,0 +1,20 @@
type: object
properties:
id:
type: number
description: The ID of the team
name:
type: string
description: The name of the team
description:
type: string
description: The description about the team
allow_auto_assign:
type: boolean
description: If this setting is turned on, the system would automatically assign the conversation to an agent in the team while assigning the conversation to a team
account_id:
type: number
description: The ID of the account with the team is a part of
is_member:
type: boolean
description: This field shows whether the current user is a part of the team

View File

@ -0,0 +1,78 @@
type: object
properties:
id:
type: number
access_token:
type: string
account_id:
type: number
available_name:
type: string
avatar_url:
type: string
confirmed:
type: boolean
display_name:
type: string
nullable: true
message_signature:
type: string
nullable: true
email:
type: string
hmac_identifier:
type: string
inviter_id:
type: number
name:
type: string
provider:
type: string
pubsub_token:
type: string
role:
type: string
enum: ['agent', 'administrator']
ui_settings:
type: object
uid:
type: string
type:
type: string
nullable: true
custom_attributes:
type: object
description: Available for users who are created through platform APIs and has custom attributes associated.
accounts:
type: array
items:
type: object
properties:
id:
type: number
name:
type: string
status:
type: string
active_at:
type: string
format: date-time
role:
type: string
enum: ['administrator', 'agent']
permissions:
type: array
items:
type: string
availability:
type: string
availability_status:
type: string
auto_offline:
type: boolean
custom_role_id:
type: number
nullable: true
custom_role:
type: object
nullable: true

View File

@ -0,0 +1,29 @@
type: object
properties:
id:
type: number
description: The ID of the webhook
url:
type: string
description: The url to which the events will be send
name:
type: string
description: The name of the webhook
subscriptions:
type: array
items:
type: string
enum: [
"conversation_created",
"conversation_status_changed",
"conversation_updated",
"contact_created",
"contact_updated",
"message_created",
"message_updated",
"webwidget_triggered"
]
description: The list of subscribed events
account_id:
type: number
description: The id of the account which the webhook object belongs to

23
swagger/index.html Normal file
View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<title>ReDoc</title>
<!-- needed for adaptive design -->
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--
ReDoc doesn't change outer page styles
-->
<style>
body {
margin: 0;
padding: 0;
font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', sans-serif;
}
</style>
</head>
<body>
<redoc spec-url='/swagger/swagger.json'></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
</body>
</html>

129
swagger/index.yml Normal file
View File

@ -0,0 +1,129 @@
openapi: '3.0.4'
info:
title: Chatwoot
description: This is the API documentation for Chatwoot server.
version: 1.1.0
termsOfService: https://www.chatwoot.com/terms-of-service/
contact:
email: hello@chatwoot.com
license:
name: MIT License
url: https://opensource.org/licenses/MIT
servers:
- url: https://app.chatwoot.com/
paths:
$ref: ./paths/index.yml
components:
schemas:
$ref: ./definitions/index.yml
parameters:
$ref: ./parameters/index.yml
securitySchemes:
userApiKey:
type: apiKey
in: header
name: api_access_token
description: This token can be obtained by visiting the profile page or via rails console. Provides access to endpoints based on the user permissions levels. This token can be saved by an external system when user is created via API, to perform activities on behalf of the user.
agentBotApiKey:
type: apiKey
in: header
name: api_access_token
description: This token should be provided by system admin or obtained via rails console. This token can be used to build bot integrations and can only access limited apis.
platformAppApiKey:
type: apiKey
in: header
name: api_access_token
description: This token can be obtained by the system admin after creating a platformApp. This token should be used to provision agent bots, accounts, users and their roles.
tags:
- name: Accounts
description: Account management APIs
- name: Account Users
description: Account user management APIs
- name: AgentBots
description: Bot integrations
- name: Users
description: User management APIs
- name: Account AgentBots
description: Account-specific Agent Bots
- name: Agents
description: Agent management APIs
- name: Canned Responses
description: Pre-defined responses for common queries
- name: Contacts
description: Contact management APIs
- name: Contact Labels
description: Manage contact labels
- name: Conversation Assignments
description: Manage conversation assignments
- name: Conversation Labels
description: Manage conversation labels
- name: Conversations
description: Conversation management APIs
- name: Custom Attributes
description: Custom fields for contacts and conversations
- name: Custom Filters
description: Saved filters for conversations
- name: Inboxes
description: Communication channels setup
- name: Integrations
description: Third-party integrations
- name: Messages
description: Message management APIs
- name: Profile
description: User profile APIs
- name: Reports
description: Analytics and reporting APIs
- name: Teams
description: Team management APIs
- name: Webhooks
description: Event notification webhooks
- name: Automation Rule
description: Workflow automation rules
- name: Help Center
description: Knowledge base management
- name: Contacts API
description: Public contact APIs
- name: Conversations API
description: Public conversation APIs
- name: Messages API
description: Public message APIs
- name: CSAT Survey Page
description: Customer satisfaction survey
x-tagGroups:
- name: Platform
tags:
- Accounts
- Account Users
- AgentBots
- Users
- name: Application
tags:
- Account AgentBots
- Account
- Agents
- Audit Logs
- Canned Responses
- Contacts
- Contact Labels
- Conversation Assignments
- Conversation Labels
- Conversations
- Custom Attributes
- Custom Filters
- Inboxes
- Integrations
- Messages
- Profile
- Reports
- Teams
- Webhooks
- Automation Rule
- Help Center
- name: Client
tags:
- Contacts API
- Conversations API
- Messages API
- name: Others
tags:
- CSAT Survey Page

View File

@ -0,0 +1,6 @@
in: path
name: account_id
schema:
type: integer
required: true
description: The numeric ID of the account

Some files were not shown because too many files have changed in this diff Show More