MaintainX Common Errors
Overview
Quick reference for diagnosing and resolving common MaintainX API errors with concrete solutions and diagnostic commands.
Prerequisites
MAINTAINX_API_KEYenvironment variable configuredcurlandjqavailable- Access to application logs
Instructions
Step 1: Diagnostic Quick Check
Run 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
Step 2: Identify the Error
Error Handling
400 Bad Request
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:
- Work orders require at minimum a
titlefield - Priority must be one of:
NONE,LOW,MEDIUM,HIGH - Status must be one of:
OPEN,IN_PROGRESS,ON_HOLD,COMPLETED,CLOSED - Dates must be ISO 8601 format:
2026-03-19T12:00:00Z
401 Unauthorized
Cause: 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:
- Regenerate key in MaintainX: Settings > Integrations > Generate Key
- Check for whitespace:
echo "'$MAINTAINX_API_KEY'" | cat -A - Ensure
Bearerprefix (notBasicorToken)
403 Forbidden
Cause: Valid key but insufficient permissions or wrong plan tier.
Fixes:
- Verify your plan supports API access (Professional or Enterprise)
- Check user role has permission for the requested operation
- For org-specific endpoints, include
X-Organization-Idheader
404 Not Found
Cause: 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:
- Confirm the ID exists (GET the resource first)
- Use
api.getmaintainx.com/v1(not/v2or missing version) - Check for typos in endpoint path (
/workordersnot/work-orders)
422 Unprocessable Entity
Cause: Request is syntactically valid but semantically incorrect.
Common triggers:
- Invalid status transition (e.g.,
CLOSEDtoIN_PROGRESS) - Referencing a non-existent
assetIdorlocationId - Invalid enum values for priority or category fields
429 Too Many Requests
Cause: 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:
- Honor the
Retry-Afterresponse header - Implement exponential backoff (see
maintainx-rate-limits) - Reduce polling frequency; use webhooks instead
500 Internal Server Error
Cause: MaintainX server-side issue.
Fixes:
- Check MaintainX Status Page
- Retry with exponential backoff (transient errors resolve themselves)
- If persistent, contact MaintainX support with request details
Output
- Identified error root cause from HTTP status code and response body
- Applied the appropriate fix from the reference above
- Verified resolution with the diagnostic quick check commands
Resources
Next Steps
For comprehensive debugging, see maintainx-debug-bundle.
Examples
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