Errors#
This guide covers all error codes returned by the VPN Signal API and how to handle them in your application.
Error Response Format#
All errors follow a consistent JSON structure:
{
"error": "error_code",
"message": "Human-readable description of the error",
"details": {
"field": "additional context"
}
}| Field | Type | Description |
|---|---|---|
error | string | Machine-readable error code |
message | string | Human-readable description |
details | object | Additional context (optional) |
HTTP Status Codes#
400 Bad Request#
The request was malformed or contained invalid data.
invalid_ip
{
"error": "invalid_ip",
"message": "The provided IP address is not valid",
"details": {
"ip": "not.an.ip",
"expected": "Valid IPv4 or IPv6 address"
}
}Fix: Ensure the IP address is a valid IPv4 (e.g., 192.168.1.1) or IPv6 (e.g., 2001:db8::1) format.
missing_ip
{
"error": "missing_ip",
"message": "IP address is required",
"details": {}
}Fix: Include the ip field in your request body.
invalid_json
{
"error": "invalid_json",
"message": "Request body must be valid JSON",
"details": {}
}Fix: Ensure your request body is valid JSON and the Content-Type header is application/json.
401 Unauthorized#
Authentication failed or API key is missing.
unauthorized
{
"error": "unauthorized",
"message": "Invalid or missing API key",
"details": {}
}Fix: Include a valid API key in the Authorization header:
Authorization: Bearer sk_live_your_key_hereinvalid_api_key
{
"error": "invalid_api_key",
"message": "The API key provided is invalid or has been revoked",
"details": {}
}Fix: Check that your API key is correct and hasn't been revoked in the dashboard.
403 Forbidden#
The API key is valid but doesn't have permission for this action.
forbidden
{
"error": "forbidden",
"message": "API key does not have access to this resource",
"details": {}
}Fix: Verify your API key has the correct permissions or upgrade your plan.
429 Too Many Requests#
You've exceeded your rate limit.
rate_limit_exceeded
{
"error": "rate_limit_exceeded",
"message": "Daily request limit exceeded",
"details": {
"limit": 100,
"reset_at": "2024-01-15T00:00:00Z"
}
}Headers included:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705276800
Retry-After: 3600Fix: Wait until the reset time or upgrade your plan for higher limits.
500 Internal Server Error#
An unexpected error occurred on our servers.
internal_error
{
"error": "internal_error",
"message": "An unexpected error occurred",
"details": {
"request_id": "req_abc123"
}
}Fix: Retry the request. If the error persists, contact support with the request_id.
503 Service Unavailable#
The service is temporarily unavailable.
service_unavailable
{
"error": "service_unavailable",
"message": "Service temporarily unavailable",
"details": {
"retry_after": 30
}
}Fix: Wait and retry. The retry_after value indicates seconds to wait.
Error Handling Examples#
JavaScript / TypeScript#
async function checkIP(ip) {
try {
const response = await fetch('https://vpnsignal.io/api/v1/check', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ ip }),
});
if (!response.ok) {
const error = await response.json();
switch (response.status) {
case 400:
throw new Error(`Invalid request: ${error.message}`);
case 401:
throw new Error('Invalid API key');
case 429:
const retryAfter = response.headers.get('Retry-After');
throw new Error(`Rate limited. Retry after ${retryAfter}s`);
default:
throw new Error(`API error: ${error.message}`);
}
}
return response.json();
} catch (error) {
console.error('VPN Signal error:', error);
throw error;
}
}Python#
import requests
from requests.exceptions import HTTPError
def check_ip(ip):
try:
response = requests.post(
'https://vpnsignal.io/api/v1/check',
headers={
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json',
},
json={'ip': ip},
)
response.raise_for_status()
return response.json()
except HTTPError as e:
error_data = e.response.json()
if e.response.status_code == 429:
retry_after = e.response.headers.get('Retry-After', 60)
raise Exception(f'Rate limited. Retry after {retry_after}s')
elif e.response.status_code == 401:
raise Exception('Invalid API key')
else:
raise Exception(f"API error: {error_data['message']}")Retry Logic with Exponential Backoff#
async function checkIPWithRetry(ip, maxRetries = 3) {
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await checkIP(ip);
} catch (error) {
lastError = error;
// Don't retry client errors (4xx)
if (error.status >= 400 && error.status < 500) {
throw error;
}
// Exponential backoff: 1s, 2s, 4s
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}Common Issues#
"Invalid API key" but key looks correct#
Tip
Check for extra whitespace or newline characters in your API key. Copy it fresh from the dashboard.
Rate limit hit unexpectedly#
- Check if multiple services are using the same API key
- Consider using separate keys for development and production
- Monitor usage in the dashboard
Intermittent 500 errors#
- Implement retry logic with exponential backoff
- Check status.vpnsignal.io for outages
- Contact support if errors persist
Need Help?#
If you're experiencing issues not covered here:
- Check the API Reference for correct usage
- Review your usage dashboard for patterns
- Contact support with your
request_idfor specific errors