From salesloft-pack
Diagnose and fix SalesLoft API errors: 401, 403, 422, 429, and 5xx. Use when encountering SalesLoft errors, debugging failed requests, or troubleshooting OAuth token issues. Trigger: "salesloft error", "fix salesloft", "salesloft not working", "salesloft 429".
npx claudepluginhub flight505/skill-forge --plugin salesloft-packThis skill is limited to using the following tools:
Quick reference for the most common SalesLoft REST API v2 errors. All errors return JSON with a message field. Rate limiting uses a cost-based system (600 cost/minute).
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 the most common SalesLoft REST API v2 errors. All errors return JSON with a message field. Rate limiting uses a cost-based system (600 cost/minute).
{ "error": "Not authorized", "error_description": "The access token is invalid" }
Causes: Token expired, revoked, or wrong environment key.
Fix:
// Check if token works
const { data } = await api.get('/me.json').catch(err => {
if (err.response?.status === 401) {
console.error('Token invalid. Refreshing...');
return refreshAccessToken(storedRefreshToken);
}
throw err;
});
{ "error": "Forbidden", "error_description": "Insufficient scope for this resource" }
Fix: Check app scopes in developer portal. Common issue: using user-level OAuth for team-level endpoints (cadences, team templates).
# Verify endpoint format -- all endpoints end with .json
curl -s -H "Authorization: Bearer $TOKEN" \
https://api.salesloft.com/v2/people/12345.json
# NOT /people/12345 (missing .json suffix)
{
"errors": [
{ "attribute": "email_address", "message": "is required" },
{ "attribute": "email_address", "message": "has already been taken" }
]
}
Common 422 causes:
| Field | Error | Solution |
|---|---|---|
email_address | required | Must include when creating a person |
email_address | already taken | Use GET /people.json?email_addresses[]=x first |
cadence_id | not active | Cadence must have current_state: 'active' |
person_id | already enrolled | Check existing cadence memberships |
X-RateLimit-Limit-Per-Minute: 600
X-RateLimit-Remaining-Per-Minute: 0
Retry-After: 42
SalesLoft uses cost-based rate limiting:
// Auto-retry with Retry-After header
api.interceptors.response.use(undefined, async (error) => {
if (error.response?.status === 429) {
const wait = parseInt(error.response.headers['retry-after'] || '60');
await new Promise(r => setTimeout(r, wait * 1000));
return api.request(error.config);
}
throw error;
});
Fix: Retry with exponential backoff. Check status.salesloft.com for outages.
# 1. Verify token
curl -s -H "Authorization: Bearer $SALESLOFT_API_KEY" \
https://api.salesloft.com/v2/me.json | jq '.data.email'
# 2. Check API status
curl -s https://status.salesloft.com/api/v2/status.json | jq '.status'
# 3. Test specific endpoint
curl -v -H "Authorization: Bearer $SALESLOFT_API_KEY" \
'https://api.salesloft.com/v2/people.json?per_page=1'
# 4. Check rate limit remaining
curl -sI -H "Authorization: Bearer $SALESLOFT_API_KEY" \
https://api.salesloft.com/v2/people.json | grep -i ratelimit
| Status | Retryable | Action |
|---|---|---|
| 401 | No | Refresh token or re-authenticate |
| 403 | No | Update app scopes in developer portal |
| 404 | No | Check endpoint URL (must end in .json) |
| 422 | No | Fix request payload |
| 429 | Yes | Wait for Retry-After header value |
| 500-503 | Yes | Exponential backoff, check status page |
For comprehensive debugging, see salesloft-debug-bundle.