Appearance
Error Codes
Complete reference for InvoisX API error codes.
Error Response Format
json
{
"success": false,
"message": "Human-readable error message",
"error_code": "ERROR_CODE",
"errors": {
// Optional: field-specific errors
}
}HTTP Status Codes
| Status | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 204 | No Content (successful delete) |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 422 | Validation Error |
| 429 | Too Many Requests |
| 500 | Server Error |
Authentication Errors
| Code | HTTP | Description |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid token |
TOKEN_EXPIRED | 401 | Token has expired |
FORBIDDEN | 403 | Insufficient permissions |
COMPANY_ACCESS_DENIED | 403 | Token not linked to company |
Example
json
{
"success": false,
"message": "Unauthenticated.",
"error_code": "UNAUTHORIZED"
}Validation Errors
| Code | HTTP | Description |
|---|---|---|
VALIDATION_FAILED | 422 | Request validation failed |
Example
json
{
"success": false,
"message": "The given data was invalid.",
"error_code": "VALIDATION_FAILED",
"errors": {
"buyerId": ["The buyer id field is required."],
"invoiceLines.0.unitPrice": ["The unit price must be a number."]
}
}Document Errors
| Code | HTTP | Description |
|---|---|---|
DOCUMENT_NOT_FOUND | 404 | Document doesn't exist |
DOCUMENT_NOT_DRAFT | 403 | Operation requires draft status |
DOCUMENT_NOT_READY | 422 | Document must be validated first |
DOCUMENT_NOT_VALID | 422 | Operation requires valid status |
DOCUMENT_READ_ONLY | 403 | Cannot modify submitted document |
Example
json
{
"success": false,
"message": "Document must be validated and in 'ready' status before submission",
"error_code": "DOCUMENT_NOT_READY"
}LHDN Errors
| Code | HTTP | Description |
|---|---|---|
LHDN_REJECTED | 422 | LHDN rejected the document |
LHDN_VALIDATION_FAILED | 422 | LHDN validation error |
LHDN_CONNECTION_ERROR | 503 | Cannot connect to LHDN |
Example
json
{
"success": false,
"message": "LHDN rejected the document",
"error_code": "LHDN_REJECTED",
"errors": {
"lhdn_error": {
"code": "ERR001",
"message": "Invalid TIN format"
}
}
}Quota Errors
| Code | HTTP | Description |
|---|---|---|
QUOTA_EXCEEDED | 429 | Submission quota exceeded |
SUBSCRIPTION_REQUIRED | 403 | Active subscription required |
SUBSCRIPTION_EXPIRED | 403 | Subscription has expired |
Example
json
{
"success": false,
"message": "Document quota exceeded. You have 0 documents remaining out of 100.",
"error_code": "QUOTA_EXCEEDED"
}Resource Errors
| Code | HTTP | Description |
|---|---|---|
NOT_FOUND | 404 | Resource not found |
BUYER_NOT_FOUND | 404 | Buyer doesn't exist |
SELLER_NOT_FOUND | 404 | On-behalf seller doesn't exist |
BUYER_HAS_INVOICES | 409 | Cannot delete buyer with invoices |
SELLER_HAS_INVOICES | 409 | Cannot delete seller with invoices |
BUYER_NOT_READY | 422 | Buyer missing required fields |
Example
json
{
"success": false,
"message": "Cannot delete buyer: has existing invoices",
"error_code": "BUYER_HAS_INVOICES"
}Rate Limit Errors
| Code | HTTP | Description |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Too many requests |
Example
json
{
"success": false,
"message": "Too many requests. Please try again in 60 seconds.",
"error_code": "RATE_LIMIT_EXCEEDED"
}Handling Errors
JavaScript
javascript
try {
const response = await api('POST', '/invoices', data);
} catch (error) {
const errorCode = error.response?.data?.error_code;
switch (errorCode) {
case 'VALIDATION_FAILED':
// Handle validation errors
const errors = error.response?.data?.errors;
Object.entries(errors).forEach(([field, messages]) => {
console.log(`${field}: ${messages.join(', ')}`);
});
break;
case 'DOCUMENT_NOT_READY':
// Validate first
await api('POST', `/documents/${id}/validate`);
break;
case 'QUOTA_EXCEEDED':
// Upgrade subscription
console.log('Please upgrade your subscription');
break;
case 'LHDN_REJECTED':
// Check LHDN error details
const lhdnError = error.response?.data?.errors?.lhdn_error;
console.log(`LHDN Error: ${lhdnError?.message}`);
break;
default:
console.log(`Error: ${error.message}`);
}
}Python
python
try:
response = api('POST', '/invoices', data)
except APIError as e:
if e.error_code == 'VALIDATION_FAILED':
for field, messages in e.errors.items():
print(f"{field}: {', '.join(messages)}")
elif e.error_code == 'DOCUMENT_NOT_READY':
api('POST', f'/documents/{id}/validate')
elif e.error_code == 'QUOTA_EXCEEDED':
print('Please upgrade your subscription')
elif e.error_code == 'LHDN_REJECTED':
lhdn_error = e.errors.get('lhdn_error', {})
print(f"LHDN Error: {lhdn_error.get('message')}")
else:
print(f"Error: {e.message}")PHP
php
try {
$response = $api->post('/invoices', $data);
} catch (RequestException $e) {
$errorCode = $e->response->json('error_code');
match ($errorCode) {
'VALIDATION_FAILED' => handleValidationErrors($e->response->json('errors')),
'DOCUMENT_NOT_READY' => $api->post("/documents/$id/validate"),
'QUOTA_EXCEEDED' => throw new Exception('Please upgrade your subscription'),
'LHDN_REJECTED' => handleLhdnError($e->response->json('errors.lhdn_error')),
default => throw $e,
};
}