From intercom-pack
Diagnose and fix Intercom API errors by HTTP status code and error type. Use when encountering Intercom errors, debugging failed API requests, or troubleshooting integration issues. Trigger with phrases like "intercom error", "fix intercom", "intercom not working", "debug intercom", "intercom 401", "intercom 429".
npx claudepluginhub flight505/skill-forge --plugin intercom-packThis skill is limited to using the following tools:
Quick reference for Intercom API errors by HTTP status code, with real error response shapes and proven solutions.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Quick reference for Intercom API errors by HTTP status code, with real error response shapes and proven solutions.
All Intercom errors return this structure:
{
"type": "error.list",
"request_id": "req_abc123",
"errors": [
{
"code": "unauthorized",
"message": "Access Token Invalid"
}
]
}
{
"type": "error.list",
"errors": [{ "code": "unauthorized", "message": "Access Token Invalid" }]
}
Causes:
Fix:
# Verify token works
curl -s https://api.intercom.io/me \
-H "Authorization: Bearer $INTERCOM_ACCESS_TOKEN" \
-H "Accept: application/json" | jq '.type'
# Should return "admin"
# If invalid, regenerate at:
# app.intercom.com > Settings > Developer Hub > Your App > Authentication
{
"type": "error.list",
"errors": [{ "code": "forbidden", "message": "You do not have permission to access this resource" }]
}
Causes:
Fix: Add the required OAuth scope in Developer Hub > OAuth Scopes.
{
"type": "error.list",
"errors": [{ "code": "not_found", "message": "User Not Found" }]
}
Causes:
user_id where contact_id is expected (or vice versa)Fix:
// Always check existence before operating
try {
const contact = await client.contacts.find({ contactId: id });
} catch (err) {
if (err instanceof IntercomError && err.statusCode === 404) {
console.log(`Contact ${id} not found, skipping`);
}
}
{
"type": "error.list",
"errors": [{ "code": "conflict", "message": "A contact matching those details already exists with id=abc123" }]
}
Causes:
external_id or emailFix:
// Search first, create if not found
async function findOrCreateContact(email: string, externalId: string) {
const existing = await client.contacts.search({
query: { field: "email", operator: "=", value: email },
});
if (existing.data.length > 0) {
return existing.data[0];
}
return client.contacts.create({
role: "user",
email,
externalId,
});
}
{
"type": "error.list",
"errors": [{ "code": "parameter_invalid", "message": "email is not a valid email address" }]
}
Causes:
Fix: Validate inputs before sending. Check the errors array for specifics.
{
"type": "error.list",
"errors": [{ "code": "rate_limit_exceeded", "message": "Rate limit exceeded" }]
}
Response headers:
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1711100060
Limits: 10,000 req/min per app, 25,000 req/min per workspace.
Fix:
import { IntercomError } from "intercom-client";
async function withBackoff<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (err) {
if (err instanceof IntercomError && err.statusCode === 429) {
if (attempt === maxRetries) throw err;
const resetAt = err.headers?.["x-ratelimit-reset"];
const waitMs = resetAt
? (parseInt(resetAt) * 1000) - Date.now() + 1000
: 1000 * Math.pow(2, attempt);
console.log(`Rate limited, waiting ${waitMs}ms`);
await new Promise(r => setTimeout(r, Math.max(waitMs, 1000)));
} else {
throw err;
}
}
}
throw new Error("Unreachable");
}
Causes: Intercom-side issue, not your fault.
Fix:
# 1. Check Intercom status
curl -s https://status.intercom.com/api/v2/summary.json | jq '.status'
# 2. Retry with backoff (same pattern as 429)
# 3. If persistent, contact Intercom support with request_id
#!/bin/bash
TOKEN="${INTERCOM_ACCESS_TOKEN}"
echo "=== Intercom API Diagnostics ==="
# Test auth
echo -n "Auth: "
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
https://api.intercom.io/me)
echo "$STATUS $([ "$STATUS" = "200" ] && echo "OK" || echo "FAIL")"
# Check rate limits
echo -n "Rate limit remaining: "
curl -s -D - -o /dev/null \
-H "Authorization: Bearer $TOKEN" \
https://api.intercom.io/me 2>/dev/null | grep -i x-ratelimit-remaining
# Intercom status
echo -n "Intercom status: "
curl -s https://status.intercom.com/api/v2/status.json | jq -r '.status.description'
| Error Code | HTTP | Retryable | Action |
|---|---|---|---|
unauthorized | 401 | No | Regenerate token |
forbidden | 403 | No | Add OAuth scope |
not_found | 404 | No | Verify resource ID |
conflict | 409 | No | Search before create |
parameter_invalid | 422 | No | Fix input data |
rate_limit_exceeded | 429 | Yes | Backoff and retry |
server_error | 500+ | Yes | Retry, check status page |
For comprehensive debugging, see intercom-debug-bundle.