GETTING STARTED
Error handling
Every error is the same shape: HTTP status plus a JSON envelope with a message, a stable code, and optional details. Check both the status and the success field.
ERROR CODES
MISSING_API_KEY
401
No key in the request headers. Add
X-API-Key.INVALID_API_KEY
401
Key is invalid or expired. Verify it in your dashboard.
PLAYER_NOT_FOUND
404
No such player. Check the slug or find them via /api/players/search.
INVALID_PARAMETER
400
A parameter value is invalid, e.g. an unknown
sort field or an attribute bound outside 0–99. details names the constraint. Note: values rejected by schema validation (bad enum, limit outside 1–100) currently return a raw validation object rather than this envelope.UNKNOWN_PARAMETERS
400
A query parameter this endpoint doesn't know. The response suggests the closest valid parameter or endpoint.
RATE_LIMIT_EXCEEDED
429
Over your limit. Wait
retryAfter seconds — see rate limits.WHEN TO RETRY
Retry 429 and 5xx with exponential backoff (snippet on the right). Never retry other 4xx errors — they mean the request itself is wrong: fix the key, the slug, or the parameter. Log the code, message, and details when things fail; they pinpoint the problem.
STUCK ON AN ERROR? OPEN A GITHUB ISSUE (WKOVERFIELD/NBA2KAPI) WITH THE REQUEST AND RESPONSE.
ERROR ENVELOPE
{
"success": false,
"error": {
"message": "A human-readable error message",
"code": "ERROR_CODE",
"details": {} // optional additional context
}
}RETRY LOGIC
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.ok) return response.json();
// Don't retry client errors (4xx except 429)
if (response.status >= 400 &&
response.status < 500 &&
response.status !== 429) {
throw new Error(`Client error: ${response.status}`);
}
// Exponential backoff: 1s, 2s, 4s
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
throw new Error('Max retries exceeded');
}