From maintainx-pack
Debugs and resolves common MaintainX API errors like 400 Bad Request, 401 Unauthorized, and 403 Forbidden with curl diagnostics, bash tests, and concrete fixes.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin maintainx-packThis skill is limited to using the following tools:
Quick reference for diagnosing and resolving common MaintainX API errors with concrete solutions and diagnostic commands.
Debugs MaintainX API integrations with bash diagnostics for environment, auth, connectivity, DNS, timing, and TypeScript axios request logging.
Diagnoses Miro REST API v2 errors by HTTP status code with curl diagnostics and fixes for bad requests, auth failures, and permissions.
Diagnoses and fixes common MindTickle API errors including 401 invalid key, 403 permissions, 404 not found, and 429 rate limits. Includes curl diagnostic script.
Share bugs, ideas, or general feedback.
Quick reference for diagnosing and resolving common MaintainX API errors with concrete solutions and diagnostic commands.
MAINTAINX_API_KEY environment variable configuredcurl and jq availableRun this first to validate connectivity and auth:
# Test 1: Verify API key is valid
curl -s -o /dev/null -w "%{http_code}" \
https://api.getmaintainx.com/v1/users?limit=1 \
-H "Authorization: Bearer $MAINTAINX_API_KEY"
# Expected: 200
# Test 2: Check API key is set
echo "Key length: ${#MAINTAINX_API_KEY}"
# Should be > 0
# Test 3: Verify DNS resolution
nslookup api.getmaintainx.com
# Should resolve to an IP
Cause: Invalid request body, missing required fields, or malformed JSON.
# Diagnose: Send a minimal valid request
curl -X POST https://api.getmaintainx.com/v1/workorders \
-H "Authorization: Bearer $MAINTAINX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title": "Diagnostic test order"}' -v 2>&1 | tail -5
Common fixes:
title fieldNONE, LOW, MEDIUM, HIGHOPEN, IN_PROGRESS, ON_HOLD, COMPLETED, CLOSED2026-03-19T12:00:00ZCause: Missing, invalid, or expired API key.
// Diagnostic wrapper
async function diagAuth() {
try {
const res = await fetch('https://api.getmaintainx.com/v1/users?limit=1', {
headers: { Authorization: `Bearer ${process.env.MAINTAINX_API_KEY}` },
});
if (res.status === 401) {
console.error('API key is invalid or expired.');
console.error('Generate a new key: MaintainX > Settings > Integrations > New Key');
} else {
console.log('Auth OK - status:', res.status);
}
} catch (e) {
console.error('Network error:', e);
}
}
Fixes:
echo "'$MAINTAINX_API_KEY'" | cat -ABearer prefix (not Basic or Token)Cause: Valid key but insufficient permissions or wrong plan tier.
Fixes:
X-Organization-Id headerCause: Resource ID does not exist or wrong endpoint path.
# Verify a resource exists before referencing it
curl -s "https://api.getmaintainx.com/v1/workorders/99999" \
-H "Authorization: Bearer $MAINTAINX_API_KEY" | jq '.message // .title'
Fixes:
api.getmaintainx.com/v1 (not /v2 or missing version)/workorders not /work-orders)Cause: Request is syntactically valid but semantically incorrect.
Common triggers:
CLOSED to IN_PROGRESS)assetId or locationIdCause: Rate limit exceeded.
// Auto-retry on 429
async function safeRequest(fn: () => Promise<any>, retries = 3) {
for (let i = 0; i <= retries; i++) {
try {
return await fn();
} catch (err: any) {
if (err?.response?.status === 429 && i < retries) {
const wait = parseInt(err.response.headers['retry-after'] || '5') * 1000;
console.warn(`Rate limited. Waiting ${wait}ms...`);
await new Promise(r => setTimeout(r, wait));
} else {
throw err;
}
}
}
}
Fixes:
Retry-After response headermaintainx-rate-limits)Cause: MaintainX server-side issue.
Fixes:
For comprehensive debugging, see maintainx-debug-bundle.
Full diagnostic script:
#!/bin/bash
echo "=== MaintainX API Diagnostics ==="
echo "Key set: $([ -n "$MAINTAINX_API_KEY" ] && echo 'YES' || echo 'NO')"
echo "Key length: ${#MAINTAINX_API_KEY}"
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
https://api.getmaintainx.com/v1/users?limit=1 \
-H "Authorization: Bearer $MAINTAINX_API_KEY")
echo "Auth status: $STATUS"
if [ "$STATUS" = "200" ]; then
WO_COUNT=$(curl -s "https://api.getmaintainx.com/v1/workorders?limit=1" \
-H "Authorization: Bearer $MAINTAINX_API_KEY" | jq '.workOrders | length')
echo "Work orders accessible: $WO_COUNT"
fi