Error Handling
How to handle API errors, status codes, and validation failures in the Renta API.
All Renta API errors return a consistent JSON structure with an HTTP status code, error type, and human-readable message.
Error Response Format
{
"error": {
"type": "validation_error",
"message": "Invalid input",
"errors": [
{
"field": "pickup_date",
"message": "Required"
},
{
"field": "return_date",
"message": "Must be after pickup_date"
}
]
}
}HTTP Status Codes
| Status | Type | Description |
|---|---|---|
400 | validation_error | Invalid request parameters |
401 | authentication_error | Invalid or missing API key |
402 | payment_failed | Payment processing failed (Stripe error) |
403 | authorization_error | Insufficient API key scope |
404 | not_found | Resource doesn't exist |
409 | conflict | Resource conflict (e.g., double booking, active bookings on delete) |
422 | validation_error | Semantic validation failure |
429 | rate_limit_exceeded | Too many requests |
500 | internal_error | Server error (auto-retried by SDK) |
Handling Errors with the SDK
The SDK throws typed exceptions for every error:
import {
Renta,
RentaError,
RentaAuthError,
RentaNotFoundError,
RentaValidationError,
RentaConflictError,
RentaRateLimitError,
RentaInternalError,
} from '@renta/sdk';
const renta = new Renta({ apiKey: process.env.RENTA_API_KEY! });
try {
await renta.bookings.create({
customer_id: 'cust_abc',
pickup_date: '2026-07-01T09:00:00Z',
return_date: '2026-07-03T17:00:00Z',
line_items: [{ fleet_item_id: 'fi_nonexistent' }],
});
} catch (err) {
if (err instanceof RentaValidationError) {
// Field-level validation errors
console.log('Validation errors:');
for (const fieldErr of err.errors) {
console.log(` ${fieldErr.field}: ${fieldErr.message}`);
}
} else if (err instanceof RentaNotFoundError) {
console.log(`Resource not found: ${err.message}`);
console.log(`Request ID: ${err.requestId}`);
} else if (err instanceof RentaConflictError) {
console.log(`Conflict: ${err.message}`);
} else if (err instanceof RentaRateLimitError) {
console.log(`Rate limited. Retry after ${err.retryAfter}s`);
} else if (err instanceof RentaAuthError) {
console.log('Check your API key');
} else if (err instanceof RentaInternalError) {
console.log('Server error — will auto-retry');
}
}Error Class Reference
| Error Class | HTTP Status | When |
|---|---|---|
RentaAuthError | 401, 403 | Invalid or insufficient API key |
RentaNotFoundError | 404 | Resource doesn't exist |
RentaValidationError | 400, 422 | Invalid input (includes errors array with field-level details) |
RentaConflictError | 409 | Resource conflict (e.g., double booking) |
RentaRateLimitError | 429 | Too many requests (has retryAfter property) |
RentaInternalError | 500+ | Server error (auto-retried by default) |
All error classes extend RentaError, which has:
interface RentaError {
message: string; // Human-readable error message
type: string; // Error type identifier
status: number; // HTTP status code
requestId?: string; // Unique request ID for support
}Automatic Retries
The SDK automatically retries on:
- 429 (Rate Limited) — respects
Retry-Afterheader, exponential backoff - 5xx (Server Errors) — exponential backoff with jitter, capped at 30s
Default: 3 retries. Disable with:
const renta = new Renta({
apiKey: process.env.RENTA_API_KEY!,
maxRetries: 0, // disable retries
});Request IDs
Every API response includes a unique x-request-id header. Include this when contacting support:
try {
await renta.bookings.get('bk_nonexistent');
} catch (err) {
if (err instanceof RentaError) {
console.log(`Request ID: ${err.requestId}`);
// → "req_abc123def456"
}
}Always log request IDs in production. They help Renta support trace specific requests across our infrastructure.