Error Handling
All API errors return a consistent JSON structure with an appropriate HTTP status code.
Error Format
{
"error": "Human-readable error message",
"details": "Additional context (optional)"
}
HTTP Status Codes
| Code | Meaning | When |
|---|---|---|
400 | Bad Request | Validation failure, malformed JSON, missing required fields |
401 | Unauthorized | Missing or invalid JWT token |
403 | Forbidden | Insufficient permissions (e.g., Free tier accessing webhooks) |
404 | Not Found | Resource does not exist (DID, dispute, webhook) |
409 | Conflict | Duplicate resource (e.g., DID already registered for address) |
429 | Too Many Requests | Rate limit exceeded for your API tier |
500 | Internal Server Error | Unexpected server error |
Common Errors
Invalid Ethereum Address
400 Bad Request
{
"error": "Invalid Ethereum address format",
"details": "Address must start with 0x followed by 40 hexadecimal characters"
}
Rate Limit Exceeded
429 Too Many Requests
{
"error": "Rate limit exceeded",
"details": "Free tier allows 10 requests per second. Upgrade at /api/v1/billing/checkout"
}
Response includes a Retry-After header indicating seconds until the next request will be accepted.
Monthly Query Limit
429 Too Many Requests
{
"error": "Monthly query limit exceeded",
"details": "Free tier allows 100 queries per month. Current usage: 100/100"
}
Webhook Tier Restriction
403 Forbidden
{
"error": "Webhooks are not available on the Free tier"
}
DID Not Found
404 Not Found
{
"error": "DID not found"
}
Invalid Proof
400 Bad Request
{
"error": "Invalid proof",
"details": "Proof verification failed: invalid encoding"
}
Handling Errors in SDKs
All CrowdProof SDKs throw typed exceptions:
import { CrowdProof, CrowdProofError } from '@crowdproof/sdk';
try {
const score = await client.getScore('0x1234...', 'DEFI_LENDING');
} catch (err) {
if (err instanceof CrowdProofError) {
console.error(`API error ${err.status}: ${err.message}`);
if (err.status === 429) {
// Back off and retry
await sleep(err.retryAfter * 1000);
}
}
}
from crowdproof import CrowdProofClient, CrowdProofError
try:
score = client.get_score("0x1234...", "DEFI_LENDING")
except CrowdProofError as e:
print(f"API error {e.status}: {e.message}")
Best Practices
- Always check HTTP status before parsing the response body
- Implement exponential backoff for
429responses - Log the full error including
detailsfor debugging - Don't retry
400/403/404— fix the request instead - Monitor
500errors — report persistent server errors to support