This connects Claude to Chatwoot's customer support API so you can manage conversations, contacts, and messages without leaving your terminal. You get the full workflow: create contacts with custom attributes, search by email or phone, spin up conversations, send messages or private notes, assign to agents, and toggle status between open, resolved, and pending. It uses the Application API with user access tokens, and all the examples show actual curl commands with proper auth headers. Worth noting it's cloud only (app.chatwoot.com), so if you're self-hosting you'll need to adjust the base URL. The skill shines when you're automating support workflows or building integrations that need to read and write conversation data programmatically.
npx -y skills add vm0-ai/vm0-skills --skill chatwoot --agent claude-codeInstalls into .claude/skills of the current project.
If requests fail, run zero doctor check-connector --env-name CHATWOOT_TOKEN or zero doctor check-connector --url https://app.chatwoot.com/api/v1/profile --method GET
All examples use the Application API with user access token.
Create a new contact in your account:
Write to /tmp/chatwoot_request.json:
{
"inbox_id": 1,
"name": "John Doe",
"email": "john@example.com",
"phone_number": "+1234567890",
"identifier": "customer_123",
"additional_attributes": {
"company": "Acme Inc",
"plan": "premium"
}
}
Then run:
curl -s -X POST "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/contacts" -H "api_access_token: $CHATWOOT_TOKEN" -H "Content-Type: application/json" -d @/tmp/chatwoot_request.json
Search contacts by email, phone, or name:
curl -s -X GET "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/contacts/search?q=john@example.com" -H "api_access_token: $CHATWOOT_TOKEN" | jq '.payload[] | {id, name, email}'
Get a specific contact by ID. Replace <contact-id> with the actual contact ID from the "Search Contacts" or "Create a Contact" response:
curl -s -X GET "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/contacts/<contact-id>" -H "api_access_token: $CHATWOOT_TOKEN"
Create a new conversation with a contact:
Write to /tmp/chatwoot_request.json:
{
"source_id": "api_conversation_123",
"inbox_id": 1,
"contact_id": 123,
"status": "open",
"message": {
"content": "Hello! How can I help you today?"
}
}
Then run:
curl -s -X POST "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/conversations" -H "api_access_token: $CHATWOOT_TOKEN" -H "Content-Type: application/json" -d @/tmp/chatwoot_request.json
Get all conversations with optional filters:
# List open conversations
curl -s -X GET "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/conversations?status=open" -H "api_access_token: $CHATWOOT_TOKEN" | jq '.data.payload[] | {id, status, contact: .meta.sender.name}'
Get details of a specific conversation. Replace <conversation-id> with the actual conversation ID from the "List Conversations" or "Create a Conversation" response:
curl -s -X GET "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/conversations/<conversation-id>" -H "api_access_token: $CHATWOOT_TOKEN"
Send a message in a conversation. Replace <conversation-id> with the actual conversation ID from the "List Conversations" response:
Write to /tmp/chatwoot_request.json:
{
"content": "Thank you for contacting us! Let me help you with that.",
"message_type": "outgoing",
"private": false
}
Then run:
curl -s -X POST "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/conversations/<conversation-id>/messages" -H "api_access_token: $CHATWOOT_TOKEN" -H "Content-Type: application/json" -d @/tmp/chatwoot_request.json
Add an internal note (not visible to customer). Replace <conversation-id> with the actual conversation ID from the "List Conversations" response:
Write to /tmp/chatwoot_request.json:
{
"content": "Customer is a VIP - handle with priority",
"message_type": "outgoing",
"private": true
}
Then run:
curl -s -X POST "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/conversations/<conversation-id>/messages" -H "api_access_token: $CHATWOOT_TOKEN" -H "Content-Type: application/json" -d @/tmp/chatwoot_request.json
Assign a conversation to an agent. Replace <conversation-id> with the actual conversation ID and <agent-id> with the agent ID from the "List Agents" response:
Write to /tmp/chatwoot_request.json:
{
"assignee_id": 1
}
Then run:
curl -s -X POST "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/conversations/<conversation-id>/assignments" -H "api_access_token: $CHATWOOT_TOKEN" -H "Content-Type: application/json" -d @/tmp/chatwoot_request.json
Change conversation status (open, resolved, pending). Replace <conversation-id> with the actual conversation ID from the "List Conversations" response:
Write to /tmp/chatwoot_request.json:
{
"status": "resolved"
}
Then run:
curl -s -X POST "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/conversations/<conversation-id>/toggle_status" -H "api_access_token: $CHATWOOT_TOKEN" -H "Content-Type: application/json" -d @/tmp/chatwoot_request.json
Get all agents in the account:
curl -s -X GET "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/agents" -H "api_access_token: $CHATWOOT_TOKEN" | jq '.[] | {id, name, email, role, availability_status}'
Get all inboxes (channels) in the account:
curl -s -X GET "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/inboxes" -H "api_access_token: $CHATWOOT_TOKEN" | jq '.payload[] | {id, name, channel_type}'
Get counts by status for dashboard:
curl -s -X GET "https://app.chatwoot.com/api/v1/accounts/$CHATWOOT_ACCOUNT_ID/conversations/meta" -H "api_access_token: $CHATWOOT_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 noteshttps://app.chatwoot.comjuliusbrussee/caveman
mattpocock/skills
shadcn/improve
obra/superpowers
forrestchang/andrej-karpathy-skills
vercel-labs/skills