Error Handling
Comprehensive guide to handling errors in the StreetVerify API. Learn about error codes, response formats, and best practices for robust error handling.
Overview
The StreetVerify API uses standard HTTP response codes and consistent JSON error responses to help you handle errors gracefully. All error responses follow a predictable format, making it easy to implement robust error handling in your applications.
Error Response Format
All API errors return a consistent JSON structure:
{
"error": "Error message describing what went wrong",
"code": "ERROR_CODE",
"details": {
// Additional context when available
}
}
Note: Successful responses return data directly without any wrapper. Only error responses use this format.
HTTP Status Codes
StreetVerify uses standard HTTP status codes to indicate the success or failure of requests:
Success Codes
- 200 OK: Request completed successfully
- 201 Created: Resource created successfully (e.g., new API key)
Client Error Codes
- 400 Bad Request: Invalid request parameters or malformed request
- 401 Unauthorized: Missing or invalid API key
- 403 Forbidden: Valid API key but insufficient permissions
- 404 Not Found: Requested resource doesn’t exist
- 422 Unprocessable Entity: Request understood but contains invalid data
- 429 Too Many Requests: Rate limit exceeded
Server Error Codes
- 500 Internal Server Error: Unexpected server error
- 502 Bad Gateway: Upstream service unavailable
- 503 Service Unavailable: Service temporarily offline
- 504 Gateway Timeout: Request timeout
Common Error Codes
Authentication Errors
// Missing API Key
{
"error": "API key is required",
"code": "MISSING_API_KEY"
}
// Invalid API Key
{
"error": "Invalid API key",
"code": "INVALID_API_KEY"
}
// Expired API Key
{
"error": "API key has been revoked",
"code": "API_KEY_REVOKED"
}
Validation Errors
// Missing Required Parameter
{
"error": "Missing required parameter: address",
"code": "MISSING_PARAMETER",
"details": {
"parameter": "address"
}
}
// Invalid Address Format
{
"error": "Invalid address format",
"code": "INVALID_ADDRESS",
"details": {
"provided": "123",
"hint": "Please provide a complete address"
}
}
// Invalid Coordinates
{
"error": "Invalid coordinates",
"code": "INVALID_COORDINATES",
"details": {
"lat": "invalid",
"lng": "-200.5",
"errors": ["Latitude must be between -90 and 90", "Longitude must be between -180 and 180"]
}
}
Rate Limiting Errors
{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"details": {
"limit": 100,
"window": "60 seconds",
"retry_after": 45
}
}
Service Errors
// Address Not Found
{
"error": "Unable to verify the provided address",
"code": "ADDRESS_NOT_FOUND",
"details": {
"address": "123 Fake Street, Nowhere, XX 00000",
"suggestions": []
}
}
// Geocoding Failed
{
"error": "Unable to geocode the provided address",
"code": "GEOCODING_FAILED",
"details": {
"reason": "Address too ambiguous"
}
}
Error Handling Best Practices
1. Always Check Response Status
const response = await fetch(url, options);
if (!response.ok) {
// Handle error
const error = await response.json();
console.error(`API Error: ${error.error} (${error.code})`);
return;
}
// Process successful response
const data = await response.json();
2. Implement Retry Logic
For transient errors (5xx status codes), implement exponential backoff:
async function apiCallWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
const data = await response.json();
if (response.status >= 500 && i < maxRetries - 1) {
// Wait before retrying (exponential backoff)
await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
continue;
}
return data;
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
}
}
}
3. Handle Rate Limits Gracefully
async function handleRateLimit(response, data) {
if (response.status === 429) {
const retryAfter = data.details?.retry_after || 60;
console.log(`Rate limited. Retrying after ${retryAfter} seconds...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
// Retry the request
}
}
4. Provide User-Friendly Messages
function getUserMessage(error) {
const messages = {
'INVALID_ADDRESS': 'Please enter a valid address',
'ADDRESS_NOT_FOUND': 'We couldn\'t find that address. Please check and try again',
'RATE_LIMIT_EXCEEDED': 'Too many requests. Please wait a moment and try again',
'INVALID_API_KEY': 'Authentication failed. Please check your API key',
'NETWORK_ERROR': 'Connection error. Please check your internet and try again'
};
return messages[error.code] || 'An unexpected error occurred. Please try again.';
}
5. Log Errors for Debugging
function logError(error, context) {
console.error({
timestamp: new Date().toISOString(),
code: error.code,
message: error.error,
details: error.details,
context: context,
stack: new Error().stack
});
}
Language-Specific Examples
Python
import requests
from time import sleep
def call_streetverify_api(endpoint, params, api_key):
headers = {'Authorization': f'Bearer {api_key}'}
try:
response = requests.get(
f'https://core.streetverify.com/api/v1/{endpoint}',
params=params,
headers=headers
)
data = response.json()
if not response.ok:
# Handle API error
if data.get('code') == 'RATE_LIMIT_EXCEEDED':
sleep(data.get('details', {}).get('retry_after', 60))
# Retry the request
else:
raise Exception(f"API Error: {data.get('error')} ({data.get('code')})")
return data
except requests.exceptions.RequestException as e:
# Handle network errors
raise Exception(f"Network error: {str(e)}")
Node.js
const axios = require('axios');
class StreetVerifyClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseURL = 'https://core.streetverify.com/api/v1';
}
async request(endpoint, params) {
try {
const response = await axios.get(`${this.baseURL}/${endpoint}`, {
params,
headers: {
'Authorization': `Bearer ${this.apiKey}`
}
});
// Response data is returned directly for successful requests
return response.data;
} catch (error) {
if (error.response) {
// API returned an error
throw new APIError(error.response.data);
} else {
// Network or other error
throw new NetworkError(error.message);
}
}
}
}
class APIError extends Error {
constructor(errorData) {
super(errorData.error);
this.code = errorData.code;
this.details = errorData.details;
}
}
class NetworkError extends Error {
constructor(message) {
super(`Network error: ${message}`);
this.code = 'NETWORK_ERROR';
}
}
Testing Error Handling
To test your error handling, you can use these test cases:
- Invalid API Key: Use an incorrect API key to test 401 errors
- Missing Parameters: Omit required parameters to test 400 errors
- Invalid Data: Send malformed data to test validation errors
- Rate Limiting: Make rapid requests to test 429 errors
- Network Issues: Test timeout and connection errors
Support
If you encounter persistent errors or need help debugging:
- Check our API Status page
- Review the error code and message carefully
- Verify your API key is valid and active
- Contact support with the error details and request ID
Remember: Good error handling improves user experience and makes debugging easier. Implement comprehensive error handling from the start!