Skip to main content

Error Response Structure

All API errors return a JSON response:
{
  "error": {
    "code": "authentication_required",
    "message": "Invalid or missing API key"
  }
}

HTTP Status Codes

Success Codes (2xx)

StatusDescriptionWhen Used
200 OKRequest succeededSuccessful GET, POST
201 CreatedResource createdSuccessful creation
204 No ContentSuccess, no bodySuccessful DELETE

Client Error Codes (4xx)

StatusDescription
400 Bad RequestMalformed request syntax or invalid parameters
401 UnauthorisedMissing or invalid API key
403 ForbiddenValid API key but insufficient permissions
404 Not FoundRequested resource does not exist
422 Unprocessable EntityRequest body validation failed
429 Too Many RequestsUsage limit exceeded

Server Error Codes (5xx)

StatusDescription
500 Internal Server ErrorUnexpected server error
503 Service UnavailableService temporarily unavailable

Error Handling with the SDK

The SDK returns typed responses that may contain either a success or error response:
import { SDK } from '@vepler/sdk';

const vepler = new SDK({ apiKey: process.env.VEPLER_API_KEY });

const response = await vepler.property.getV1PropertyLocationIds({
  locationIds: 'p_0x000123456789'
});

// Check for successful response
if (response.propertyListResponse) {
  console.log('Success:', response.propertyListResponse.result);
}

// Check for error response
if (response.errorResponse) {
  console.error('Error:', response.errorResponse.error);
  console.error('Code:', response.errorResponse.code);
}

Error Handling with HTTP

const response = await fetch('https://api.vepler.com/v1/property/p_0x000123456789', {
  headers: { 'x-api-key': process.env.VEPLER_API_KEY }
});

if (!response.ok) {
  const error = await response.json();

  switch (response.status) {
    case 401:
      console.error('Invalid API key');
      break;
    case 404:
      console.error('Resource not found');
      break;
    case 429:
      console.error('Usage limit exceeded — retry shortly');
      break;
    default:
      console.error('Error:', error);
  }
}

Retry Strategy

Implement exponential backoff for transient errors (429, 5xx):
async function retryWithBackoff(
  fn: () => Promise<unknown>,
  maxRetries = 3,
  baseDelay = 1000
): Promise<unknown> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      const err = error as { statusCode?: number };

      // Don't retry client errors (except 429)
      if (err.statusCode && err.statusCode >= 400 && err.statusCode < 500 && err.statusCode !== 429) {
        throw error;
      }

      if (i === maxRetries - 1) throw error;

      const delay = baseDelay * Math.pow(2, i);
      console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

Best Practices

Never assume API calls will succeed:
const response = await vepler.property.getV1PropertyLocationIds({
  locationIds: id
});

if (response.errorResponse) {
  // Handle error
  console.error(response.errorResponse);
  return null;
}

return response.propertyListResponse;
Handle different status codes appropriately:
function handleError(statusCode: number): void {
  switch (statusCode) {
    case 401:
      console.error('Check your API key');
      break;
    case 404:
      console.log('Resource not found');
      break;
    case 429:
      console.log('Slow down — retry shortly');
      break;
    default:
      console.error('Unexpected error:', statusCode);
  }
}
Set reasonable timeouts:
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch('https://api.vepler.com/v1/property/health', {
    headers: { 'x-api-key': process.env.VEPLER_API_KEY! },
    signal: controller.signal
  });
} finally {
  clearTimeout(timeout);
}

Next Steps