Error Reference
All API errors return a consistent JSON envelope:
{
"success": false,
"error": "Descriptive error message",
"statusCode": 400
}
Authentication Errors
| Scenario | Status | Typical message |
|---|---|---|
Missing x-api-key header | 401 | API key is required |
| Invalid or revoked API key | 401 | Invalid API key |
Missing x-admin-key | 401 | Admin key is required |
| Invalid admin key | 401 | Invalid admin key |
| Expired JWT token | 401 | Token expired |
| Invalid JWT token | 401 | Invalid token |
| Insufficient permissions | 403 | Access denied |
| Tenant is suspended | 403 | Tenant account is suspended |
Tenant & Onboarding Errors
| Scenario | Status | Typical message |
|---|---|---|
| Tenant not found | 404 | Tenant not found |
| Duplicate TIN | 400 | A tenant with this TIN already exists |
| TIN format invalid | 422 | TIN must be between 10 and 20 characters |
| BRN format invalid | 422 | Business registration number must be between 5 and 50 characters |
| Tenant not active | 403 | Tenant is not active. Complete onboarding first |
Credential Errors
| Scenario | Status | Typical message |
|---|---|---|
| Invalid PEM certificate | 422 | Certificate must be a valid PEM-encoded certificate |
| Public key too short | 422 | Public key must be at least 50 characters |
| Missing credentials | 400 | FIRS credentials have not been configured |
ERP & Validation Errors
| Scenario | Status | Typical message |
|---|---|---|
| Unsupported ERP type | 422 | ERP type is not supported |
| Invalid base URL | 422 | baseUrl must be a valid URI |
| Transform failed | 422 | Could not map invoice fields to FIRS schema |
| Validation failed | 422 | Invoice failed FIRS schema validation |
| Invoice ID key not found | 422 | Could not locate invoice ID at path: invoice.ref |
API Key Errors
| Scenario | Status | Typical message |
|---|---|---|
| API key not found | 404 | API key not found |
| Key already revoked | 400 | API key has already been revoked |
| Revocation reason too short | 422 | Reason must be at least 5 characters |
Team Errors
| Scenario | Status | Typical message |
|---|---|---|
| User not found | 404 | Team member not found |
| Email already in team | 400 | A team member with this email already exists |
| Invalid role | 422 | Role must be one of: admin, member, viewer |
| Invalid invite token | 400 | Invitation token is invalid or has expired |
Rate Limiting
| Scenario | Status | Notes |
|---|---|---|
| Rate limit exceeded | 429 | Slow down — check Retry-After header |
Handling Errors in Code
const response = await fetch('https://e-invoicing-staging.vercel.app/v1/tenants/', {
method: 'POST',
headers: {
'x-admin-key': process.env.ADMIN_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({ ... }),
});
const result = await response.json();
if (!result.success) {
console.error(`Error ${result.statusCode}: ${result.error}`);
// Handle specific error scenarios
}