Chatwoot
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
When to Use
Use this skill when you need to:
Manage contacts - create, search, and update customer profiles Handle conversations - create, assign, and track support conversations Send messages - reply to customers or add internal notes List agents - get support team information Automate workflows - integrate with CRM, ticketing, or notification systems Prerequisites Set up Chatwoot (Cloud or Self-hosted) Log in and go to Profile Settings to get your API access token Note your Account ID from the URL (e.g., /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 Types 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 $VAR in a command that pipes to another command, wrap the command containing $VAR in bash -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 .
How to Use
All examples use the Application API with user access token.
- Create a Contact
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:
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 @/tmp/chatwoot_request.json'
- Search Contacts
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 Contact Details
Get a specific contact by ID. Replace
bash -c 'curl -s -X GET "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/contacts/
- Create a Conversation
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:
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 @/tmp/chatwoot_request.json'
- List Conversations
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 Conversation Details
Get details of a specific conversation. Replace
bash -c 'curl -s -X GET "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/
- Send a Message
Send a message in a conversation. Replace
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:
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/
- Add Private Note
Add an internal note (not visible to customer). Replace
Write to /tmp/chatwoot_request.json:
{ "content": "Customer is a VIP - handle with priority", "message_type": "outgoing", "private": true }
Then run:
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/
- Assign Conversation
Assign a conversation to an agent. Replace
Write to /tmp/chatwoot_request.json:
{ "assignee_id": 1 }
Then run:
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/
- Update Conversation Status
Change conversation status (open, resolved, pending). Replace
Write to /tmp/chatwoot_request.json:
{ "status": "resolved" }
Then run:
bash -c 'curl -s -X POST "${CHATWOOT_BASE_URL}/api/v1/accounts/${CHATWOOT_ACCOUNT_ID}/conversations/
- List Agents
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}'
- List Inboxes
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 Conversation Counts
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'
Conversation Status Status Description open Active conversation resolved Closed/completed pending Waiting for response snoozed Temporarily paused Message Types Type Value Description Outgoing outgoing Agent to customer Incoming incoming Customer to agent Private private: true Internal note (not visible to customer) Response Fields Contact Field Description id Contact ID name Contact name email Email address phone_number Phone number identifier External system ID custom_attributes Custom fields Conversation Field Description id Conversation ID inbox_id Channel/inbox ID status Current status assignee Assigned agent contact Customer info Message Field Description id Message ID content Message text message_type incoming/outgoing private Is internal note status sent/delivered/read/failed Guidelines Get API token from Profile Settings: Log into Chatwoot → Profile → Access Token Account ID is in URL: Look at /app/accounts/{id}/... in your browser Inbox ID is required: Get inbox IDs first with the list inboxes endpoint Use source_id for conversations: Required to create conversations via API Private messages: Set private: true for internal notes Self-hosted: Change CHATWOOT_BASE_URL to your instance URL Webhooks recommended: Use webhooks for real-time updates instead of polling