Error Handling
Understanding and handling SafePays API V2 errors
Error Response Format
All error responses from the SafePays API V2 follow a consistent format:
{
"error": "Descriptive error message"
}HTTP Status Codes
Success Codes
| Code | Name | Description |
|---|---|---|
| 200 | OK | Request successful |
| 201 | Created | Resource created successfully |
Client Error Codes
| Code | Name | Description |
|---|---|---|
| 400 | Bad Request | Invalid request parameters or missing required fields |
| 401 | Unauthorized | Invalid or missing API key |
| 404 | Not Found | Resource not found |
| 409 | Conflict | Resource already exists (e.g., duplicate customer email) |
Server Error Codes
| Code | Name | Description |
|---|---|---|
| 500 | Internal Server Error | Server error — retry or contact support |
Common Error Messages
Authentication Errors
Invalid API Key — 401
{
"error": "Invalid API Key"
}Cause: API key is incorrect, missing, or has been revoked. Verify your API key in the dashboard.
Validation Errors
Missing Required Fields — 400
{
"error": "name and email are required"
}Cause: Required fields not provided in the request body.
Missing Webhook — 400
{
"error": "webhook parameter is required"
}Cause: The webhook query parameter was not provided when creating an invoice.
Missing API Key (GET) — 400
{
"error": "api_key parameter is required"
}Cause: The api_key query parameter was not provided on a GET request.
Resource Errors
Customer Not Found — 404
{
"error": "Customer not found"
}Cause: The provided customer_id does not exist. Verify the ID or create the customer first.
Invoice Not Found — 404
{
"error": "Invoice not found"
}Cause: The provided invoice_id does not exist.
Duplicate Customer — 409
{
"error": "Customer with this email already exists"
}Cause: A customer with the same email address already exists in your account.
Error Handling by Endpoint
POST /api/v2/customer
| Status | Error | Cause |
|---|---|---|
| 400 | name and email are required | Missing name or email in request body |
| 401 | Invalid API Key | Invalid or missing api_key |
| 409 | Customer with this email already exists | Duplicate email address |
POST /api/v2/invoice
| Status | Error | Cause |
|---|---|---|
| 400 | email or customer_id is required | Neither customer_id nor email provided |
| 400 | amount or items are required | Neither amount nor items provided |
| 400 | Invoice amount must be greater than 0 | Zero or negative amount |
| 400 | Invalid redirect_url / Invalid webhook_url | Malformed URL |
| 400 | Invalid due_date format. Use YYYY-MM-DD | Bad date format |
| 401 | api_key is required / Invalid API Key | Missing or invalid api_key |
| 403 | This vendor account has been banned. | Account suspended |
| 404 | Customer not found | Invalid customer_id |
| 502 | Payment provider error (status) | Upstream provider failure |
GET /api/v2/invoice/{id}
| Status | Error | Cause |
|---|---|---|
| 400 | api_key parameter is required | Missing api_key query parameter |
| 401 | Invalid API Key | Invalid api_key |
| 404 | Invoice not found | Invalid invoice_id |
GET /api/v2/customer/{id}
| Status | Error | Cause |
|---|---|---|
| 400 | api_key parameter is required | Missing api_key query parameter |
| 401 | Invalid API Key | Invalid api_key |
| 404 | Customer not found | Invalid customer_id |
Best Practices
Check HTTP Status Codes
Always check the HTTP status code before parsing the response body. A 2xx status indicates success, while 4xx and 5xx indicate errors.
Handle Errors Gracefully
async function safepaysRequest(url, options) {
const response = await fetch(url, options);
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `HTTP ${response.status}`);
}
return data;
}
try {
const result = await safepaysRequest(
'https://app.safepays.com/api/v2/customer',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
api_key: 'your_api_key_here',
name: 'John Doe',
email: 'john@example.com'
})
}
);
console.log('Success:', result);
} catch (error) {
console.error('API Error:', error.message);
}Retry on Server Errors
For 500 errors, implement retry logic with exponential backoff. Do not retry 4xx errors — these indicate issues with your request that need to be fixed.
async function requestWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.ok) {
return response.json();
}
if (response.status >= 400 && response.status < 500) {
const error = await response.json();
throw new Error(error.error);
}
const delay = Math.min(1000 * Math.pow(2, i), 10000);
await new Promise(resolve => setTimeout(resolve, delay));
}
throw new Error('Request failed after retries');
}Getting Help
If you continue experiencing issues:
- Double-check your request against the API documentation
- Verify your API key is correct and active
- Contact support@safepays.com with the error message and request details