intercom-api
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.
# 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.
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.
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
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
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.
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
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.
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
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
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
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
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
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
- List articles to find the one to edit
- Get article details to read current content
- Draft updated content - body must be valid HTML (
<h2>,<p>,<ul><li>,<strong>,<a href>) - Update as draft first (
"state": "draft") - Confirm with user before publishing
- 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 |