intercom-api
Perform write operations on Intercom conversations and Help Center articles via REST API. Use when you need to reply, add notes, assign, close, snooze, or reopen conversations, or create/update Help Center articles. Trigger when: user says 'reply to intercom', 'close conversation', 'add note', 'update help article', 'assign conversation', or any Intercom write operation.
intercomsupportcustomer-servicehelp-center
Security Vetted
Reviewed by AI agents and approved by humans.
Permissions Required
BashReadEditWrite Skill Instructions
# Intercom API (Write Operations)
Perform write operations on Intercom conversations and Help Center via REST API using curl.
## Authentication
Store your Intercom Personal Access Token as an environment variable. The `Intercom-Version: 2.11` header is **required** on all requests.
```bash
# Set your token (add to ~/.zshenv, ~/.bashrc, or ~/.zshrc)
export INTERCOM_ACCESS_TOKEN="your-token-here"
# Test authentication
curl -s https://api.intercom.io/me \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['name'], d['email'])"
```
## Conversation Write Operations
All conversation actions use `$CONVERSATION_ID`. Find this from the Intercom URL or search API.
### Reply to Conversation (Customer-Visible)
Sends a reply that the customer can see.
```bash
CONVERSATION_ID="12345678"
ADMIN_ID="YOUR_ADMIN_ID"
curl -s -X POST "https://api.intercom.io/conversations/$CONVERSATION_ID/reply" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
-d "{
\"message_type\": \"comment\",
\"type\": \"admin\",
\"admin_id\": \"$ADMIN_ID\",
\"body\": \"Your reply text here.\"
}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('Reply sent:', d.get('id', d))"
```
### Add Internal Note
Adds a note visible only to admins (not the customer). Notes support HTML.
```bash
CONVERSATION_ID="12345678"
ADMIN_ID="YOUR_ADMIN_ID"
curl -s -X POST "https://api.intercom.io/conversations/$CONVERSATION_ID/reply" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
-d "{
\"message_type\": \"note\",
\"type\": \"admin\",
\"admin_id\": \"$ADMIN_ID\",
\"body\": \"<p>Investigation notes here.</p><p>Root cause: ...</p>\"
}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('Note added:', d.get('id', d))"
```
### Assign Conversation
```bash
CONVERSATION_ID="12345678"
ADMIN_ID="YOUR_ADMIN_ID" # Admin performing the assignment
ASSIGNEE_ID="TARGET_ADMIN_ID" # Who to assign to
curl -s -X POST "https://api.intercom.io/conversations/$CONVERSATION_ID/parts" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
-d "{
\"message_type\": \"assignment\",
\"type\": \"admin\",
\"admin_id\": \"$ADMIN_ID\",
\"assignee_id\": \"$ASSIGNEE_ID\",
\"body\": \"Assigning to support team for follow-up.\"
}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('Assigned:', d.get('conversation_parts', {}).get('conversation_parts', [{}])[0].get('id', d))"
```
### Close Conversation
```bash
CONVERSATION_ID="12345678"
ADMIN_ID="YOUR_ADMIN_ID"
curl -s -X POST "https://api.intercom.io/conversations/$CONVERSATION_ID/parts" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
-d "{
\"message_type\": \"close\",
\"type\": \"admin\",
\"admin_id\": \"$ADMIN_ID\"
}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('Closed. State:', d.get('state', d))"
```
### Snooze Conversation
Snooze until a Unix timestamp.
```bash
CONVERSATION_ID="12345678"
ADMIN_ID="YOUR_ADMIN_ID"
# macOS: $(date -v+1d +%s) Linux: $(date -d '+1 day' +%s)
SNOOZE_UNTIL=$(date -v+1d +%s)
curl -s -X POST "https://api.intercom.io/conversations/$CONVERSATION_ID/parts" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
-d "{
\"message_type\": \"snoozed\",
\"type\": \"admin\",
\"admin_id\": \"$ADMIN_ID\",
\"snoozed_until\": $SNOOZE_UNTIL
}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('Snoozed until:', d.get('snoozed_until', d))"
```
### Open (Reopen) Conversation
```bash
CONVERSATION_ID="12345678"
ADMIN_ID="YOUR_ADMIN_ID"
curl -s -X POST "https://api.intercom.io/conversations/$CONVERSATION_ID/parts" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
-d "{
\"message_type\": \"open\",
\"type\": \"admin\",
\"admin_id\": \"$ADMIN_ID\"
}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('Opened. State:', d.get('state', d))"
```
## Tracker Tickets
Create tracker tickets to group related customer issues.
```bash
python3 - <<'PYEOF'
import subprocess, json, os
token = os.environ["INTERCOM_ACCESS_TOKEN"]
payload = json.dumps({
"ticket_type_id": "YOUR_TICKET_TYPE_ID",
"ticket_attributes": {
"_default_title_": "Short bug title",
"_default_description_": "Description of the issue and any linked references"
},
"contacts": []
})
result = subprocess.run([
"curl", "-s", "-X", "POST", "https://api.intercom.io/tickets",
"-H", f"Authorization: Bearer {token}",
"-H", "Content-Type: application/json",
"-H", "Accept: application/json",
"-H", "Intercom-Version: 2.11",
"-d", payload
], capture_output=True, text=True)
d = json.loads(result.stdout)
print("Ticket ID:", d.get("ticket_id"))
print("Internal ID:", d.get("id"))
PYEOF
```
Use `python3` heredoc pattern (not inline curl) to avoid shell escaping issues with apostrophes in the description.
**Note:** Linking tracker tickets to conversations is UI-only. The REST API linking endpoints silently fail. Use the Intercom UI to link tickets to conversations.
## Help Center Management
### List All Articles
```bash
curl -s "https://api.intercom.io/articles" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
| python3 -c "
import sys, json
d = json.load(sys.stdin)
for a in d.get('data', []):
print(f\"{a['id']:10} {a.get('state',''):10} {a.get('title','')[:60]}\")
print(f'\nTotal: {len(d.get(\"data\", []))}')
"
```
### Get Article Details
```bash
ARTICLE_ID="12345"
curl -s "https://api.intercom.io/articles/$ARTICLE_ID" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
| python3 -c "
import sys, json
d = json.load(sys.stdin)
print('Title:', d.get('title'))
print('State:', d.get('state'))
print('URL:', d.get('url'))
print()
print('Body (truncated):')
print(d.get('body', '')[:500])
"
```
### Create Article
```bash
AUTHOR_ID="YOUR_ADMIN_ID"
PARENT_ID="YOUR_COLLECTION_ID"
curl -s -X POST "https://api.intercom.io/articles" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
-d "{
\"title\": \"Article Title\",
\"description\": \"Short description shown in search results\",
\"body\": \"<h2>Overview</h2><p>Content here...</p>\",
\"author_id\": $AUTHOR_ID,
\"state\": \"draft\",
\"parent_id\": $PARENT_ID,
\"parent_type\": \"collection\"
}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('Created:', d.get('id'), d.get('title'), d.get('url'))"
```
States: `"draft"` (default) or `"published"`. Parent types: `"collection"` or `"section"`.
### Update Article
```bash
ARTICLE_ID="12345"
curl -s -X PUT "https://api.intercom.io/articles/$ARTICLE_ID" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
-d "{
\"title\": \"Updated Title\",
\"body\": \"<h2>Overview</h2><p>Updated content...</p>\",
\"state\": \"published\"
}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('Updated:', d.get('id'), d.get('title'), d.get('state'))"
```
### List Collections
```bash
curl -s "https://api.intercom.io/help_center/collections" \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Accept: application/json" \
-H "Intercom-Version: 2.11" \
| python3 -c "
import sys, json
d = json.load(sys.stdin)
for c in d.get('data', []):
print(f\"{c['id']:10} {c.get('name','')}\")
"
```
## Help Center Editing Workflow
1. **List articles** to find the one to edit
2. **Get article details** to read current content
3. **Draft updated content** - body must be valid HTML (`<h2>`, `<p>`, `<ul><li>`, `<strong>`, `<a href>`)
4. **Update as draft** first (`"state": "draft"`)
5. **Confirm with user** before publishing
6. **Publish** by updating `"state": "published"`
## Error Handling
| Status | Meaning | Fix |
|--------|---------|-----|
| 401 | Invalid token | Check `INTERCOM_ACCESS_TOKEN` is set and valid |
| 403 | Insufficient permissions | Token needs write scopes |
| 404 | Resource not found | Verify the ID |
| 422 | Invalid request body | Check required fields and types |
| 429 | Rate limited | Wait and retry; Intercom limit is 1000/min |
## Quick Reference
| Operation | Endpoint | Method | Key Field |
|-----------|----------|--------|-----------|
| Reply (visible) | `/conversations/{id}/reply` | POST | `message_type: "comment"` |
| Internal note | `/conversations/{id}/reply` | POST | `message_type: "note"` |
| Assign | `/conversations/{id}/parts` | POST | `message_type: "assignment"` |
| Close | `/conversations/{id}/parts` | POST | `message_type: "close"` |
| Snooze | `/conversations/{id}/parts` | POST | `message_type: "snoozed"` |
| Open/reopen | `/conversations/{id}/parts` | POST | `message_type: "open"` |
| List articles | `/articles` | GET | |
| Get article | `/articles/{id}` | GET | |
| Create article | `/articles` | POST | `state: "draft"/"published"` |
| Update article | `/articles/{id}` | PUT | |
| List collections | `/help_center/collections` | GET | |