Chatwoot customer support API via curl. Use this skill to manage contacts, conversations, and messages for multi-channel customer support.
/plugin marketplace add vm0-ai/api0/plugin install api0@api0This skill inherits all available tools. When active, it can use any tool Claude has access to.
Use Chatwoot via direct curl calls to manage customer support across multiple channels (website, email, WhatsApp, etc.).
Official docs:
https://developers.chatwoot.com/api-reference/introduction
Use this skill when you need to:
/app/accounts/1/...)export CHATWOOT_API_TOKEN="your-api-access-token"
export CHATWOOT_ACCOUNT_ID="1"
export CHATWOOT_BASE_URL="https://app.chatwoot.com" # or your self-hosted URL
| API Type | Auth | Use Case |
|---|---|---|
| Application API | User access_token | Agent/admin automation |
| Client API | inbox_identifier | Custom chat interfaces |
| Platform API | Platform App token | Multi-tenant management (self-hosted only) |
Important: When using
$VARin a command that pipes to another command, wrap the command containing$VARinbash -c '...'. Due to a Claude Code bug, environment variables are silently cleared when pipes are used directly.bash -c 'curl -s "https://api.example.com" -H "Authorization: Bearer $API_KEY"' | jq .
All examples use the Application API with user access token.
Create a new contact in your account:
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/contacts" -H "api_access_token: ${CHATWOOT_API_TOKEN}" -H "Content-Type: application/json" -d '"'"'{
"inbox_id": 1,
"name": "John Doe",
"email": "john@example.com",
"phone_number": "+1234567890",
"identifier": "customer_123",
"additional_attributes": {
"company": "Acme Inc",
"plan": "premium"
}
}'"'"' | jq '"'"'{id, name, email, phone_number}'"'"''
Search contacts by email, phone, or name:
bash -c 'curl -s -X GET "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/contacts/search?q=john@example.com" -H "api_access_token: ${CHATWOOT_API_TOKEN}"' | jq '.payload[] | {id, name, email}'
Get a specific contact by ID:
Note: Get
CONTACT_IDfrom the "Search Contacts" response (idfield) or from the "Create a Contact" response.
CONTACT_ID=123
bash -c 'curl -s -X GET "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/contacts/${CONTACT_ID}" -H "api_access_token: ${CHATWOOT_API_TOKEN}"' | jq '{id, name, email, phone_number, custom_attributes}'
Create a new conversation with a contact:
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations" -H "api_access_token: ${CHATWOOT_API_TOKEN}" -H "Content-Type: application/json" -d '"'"'{
"source_id": "api_conversation_123",
"inbox_id": 1,
"contact_id": 123,
"status": "open",
"message": {
"content": "Hello! How can I help you today?"
}
}'"'"' | jq '"'"'{id, inbox_id, status}'"'"''
Get all conversations with optional filters:
# List open conversations
bash -c 'curl -s -X GET "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations?status=open" -H "api_access_token: ${CHATWOOT_API_TOKEN}"' | jq '.data.payload[] | {id, status, contact: .meta.sender.name}'
Get details of a specific conversation:
Note: Get
CONVERSATION_IDfrom the "List Conversations" response (idfield) or from the "Create a Conversation" response.
CONVERSATION_ID=123
bash -c 'curl -s -X GET "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/${CONVERSATION_ID}" -H "api_access_token: ${CHATWOOT_API_TOKEN}"' | jq '{id, status, inbox_id, messages_count: .messages | length}'
Send a message in a conversation:
Note: Get
CONVERSATION_IDfrom the "List Conversations" response (idfield).
CONVERSATION_ID=123
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/${CONVERSATION_ID}/messages" -H "api_access_token: ${CHATWOOT_API_TOKEN}" -H "Content-Type: application/json" -d '"'"'{
"content": "Thank you for contacting us! Let me help you with that.",
"message_type": "outgoing",
"private": false
}'"'"' | jq '"'"'{id, content, status}'"'"''
Add an internal note (not visible to customer):
Note: Get
CONVERSATION_IDfrom the "List Conversations" response (idfield).
CONVERSATION_ID=123
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/${CONVERSATION_ID}/messages" -H "api_access_token: ${CHATWOOT_API_TOKEN}" -H "Content-Type: application/json" -d '"'"'{
"content": "Customer is a VIP - handle with priority",
"message_type": "outgoing",
"private": true
}'"'"' | jq '"'"'{id, content, private}'"'"''
Assign a conversation to an agent:
Note: Get
CONVERSATION_IDfrom the "List Conversations" response (idfield). GetAGENT_IDfrom the "List Agents" response (idfield).
CONVERSATION_ID=123
AGENT_ID=1
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/${CONVERSATION_ID}/assignments" -H "api_access_token: ${CHATWOOT_API_TOKEN}" -H "Content-Type: application/json" -d "{\"assignee_id\": ${AGENT_ID}}"' | jq .
Change conversation status (open, resolved, pending):
Note: Get
CONVERSATION_IDfrom the "List Conversations" response (idfield).
CONVERSATION_ID=123
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/${CONVERSATION_ID}/toggle_status" -H "api_access_token: ${CHATWOOT_API_TOKEN}" -H "Content-Type: application/json" -d '"'"'{"status": "resolved"}'"'"'' | jq '{id, status}'
Get all agents in the account:
bash -c 'curl -s -X GET "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/agents" -H "api_access_token: ${CHATWOOT_API_TOKEN}"' | jq '.[] | {id, name, email, role, availability_status}'
Get all inboxes (channels) in the account:
bash -c 'curl -s -X GET "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/inboxes" -H "api_access_token: ${CHATWOOT_API_TOKEN}"' | jq '.payload[] | {id, name, channel_type}'
Get counts by status for dashboard:
bash -c 'curl -s -X GET "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/meta" -H "api_access_token: ${CHATWOOT_API_TOKEN}"' | jq '.meta.all_count, .meta.mine_count'
| Status | Description |
|---|---|
open | Active conversation |
resolved | Closed/completed |
pending | Waiting for response |
snoozed | Temporarily paused |
| Type | Value | Description |
|---|---|---|
| Outgoing | outgoing | Agent to customer |
| Incoming | incoming | Customer to agent |
| Private | private: true | Internal note (not visible to customer) |
| Field | Description |
|---|---|
id | Contact ID |
name | Contact name |
email | Email address |
phone_number | Phone number |
identifier | External system ID |
custom_attributes | Custom fields |
| Field | Description |
|---|---|
id | Conversation ID |
inbox_id | Channel/inbox ID |
status | Current status |
assignee | Assigned agent |
contact | Customer info |
| Field | Description |
|---|---|
id | Message ID |
content | Message text |
message_type | incoming/outgoing |
private | Is internal note |
status | sent/delivered/read/failed |
/app/accounts/{id}/... in your browserprivate: true for internal notesCHATWOOT_BASE_URL to your instance URL