Skip to main content

Error Handling

The API returns standard HTTP codes accompanied by structured error messages.

Error Format

All errors follow this format:

{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error description"
}
}

HTTP Codes

CodeMeaningWhen
200OKSuccessful request
401UnauthorizedMissing or invalid authentication
402Payment RequiredInsufficient credits
403ForbiddenInsufficient scope
404Not FoundResource not found
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer error

Common Error Codes

Authentication

{
"error": {
"code": "MISSING_API_KEY",
"message": "Authorization header missing"
}
}
{
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid or revoked API key"
}
}

Permissions

{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "Scope 'appointments:create' required"
}
}

Resources

{
"error": {
"code": "APPOINTMENT_NOT_FOUND",
"message": "Appointment with id 12345 not found"
}
}

Rate Limiting

{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 3600 seconds"
}
}

Headers: Retry-After: 3600

Credits

{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Your organization has 0 credits remaining"
}
}

Error Handling in Code

With cURL

response=$(curl -s -w "\n%{http_code}" ...)
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | head -n-1)

if [ $http_code -ne 200 ]; then
echo "Error: $body"
fi

With SDKs

SDKs automatically handle errors with typed exceptions:

try {
const appointment = await client.appointments.create({...});
} catch (error) {
if (error.code === 'INSUFFICIENT_CREDITS') {
// Redirect to recharge page
} else if (error.code === 'RATE_LIMIT_EXCEEDED') {
// Retry with backoff
}
}

Retry Logic

For temporary errors (429, 500, 503), implement retry with exponential backoff:

async function retryRequest(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.status === 429 || error.status >= 500) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error; // Non-retriable error
}
}
}
throw new Error('Max retries exceeded');
}

Next Steps