Error Codes
Standardized API error code reference — response structure, HTTP status codes, naming conventions, and error handling best practices.
The M2P Prepaid Platform uses a standardized error code system across all APIs. This section provides complete error code catalogs organized by service.
Error Response Structure
{
"type": "https://www.m2pfintech.com/problem/problem-with-message",
"title": "Brief error summary",
"status": 400,
"detail": "Detailed error message with context",
"path": "/api/endpoint/path",
"message": "error.http.400",
"business.code": "PPCUST_001"
}| Field | Type | Description |
|---|---|---|
type | string | Error type URI |
title | string | Brief error summary |
status | integer | HTTP status code |
detail | string | Detailed error description with context |
path | string | API endpoint that returned the error |
message | string | Error category |
business.code | string | Business error code (e.g., PP_MIDD_020, PPCUST_002) |
HTTP Status Codes
| HTTP Code | Category | When Used | Retryable |
|---|---|---|---|
| 200 | Success | Request processed successfully | — |
| 400 | Client Error | Invalid request payload, validation failures | No |
| 401 | Unauthorized | Missing or invalid authentication | No |
| 403 | Forbidden | Valid auth but insufficient permissions | No |
| 404 | Not Found | Resource doesn't exist | No |
| 409 | Conflict | Business rule violations, duplicate data | No |
| 429 | Too Many Requests | Rate limit exceeded | Yes (with backoff) |
| 500 | Server Error | Internal server errors | Yes (after investigation) |
| 503 | Service Unavailable | Service temporarily down | Yes (with backoff) |
Naming Convention
Error codes follow the pattern: {SERVICE_PREFIX}_{SEQUENCE_NUMBER}
| Prefix | Service | Example |
|---|---|---|
PP_MIDD | pp-middleware | PP_MIDD_020 |
PPCUST | Customer API | PPCUST_045 |
PP_CORP | Corporate API | PP_CORP_128 |
Error messages support dynamic placeholders: {0}, {1}, etc.
Example: "Invalid Product id {0}" → "Invalid Product id PROD_12345"
Error Categories
| Category | HTTP Code | Description |
|---|---|---|
| Validation Errors | 400 | Invalid request data, format issues, missing fields |
| Business Logic Errors | 409 | Business rule violations, conflicting states |
| Resource Not Found | 404 | Requested entity doesn't exist |
| Auth Errors | 401/403 | Authentication / authorization failures |
| System Errors | 500/503 | Technical / infrastructure failures |
Error Catalogs
Middleware Errors
PP_MIDD_001 – PP_MIDD_040: OTP, issuance, and orchestration layer errors.
Customer Errors
PPCUST_001 – PPCUST_130: Customer, card, wallet, transaction, and IMPS errors.
Corporate Errors
PP_CORP_001 – PP_CORP_192: Issuance, kit, wallet, forex, and hierarchy errors.
Authorization Declines
Card network authorization decline reason codes and handling.
Error Handling Best Practices
if (response.status === 200) {
processSuccess(response.data);
} else if (response.status === 400) {
handleValidationError(response.data); // Fix request
} else if (response.status === 409) {
handleBusinessError(response.data); // Inform user
} else if (response.status >= 500) {
scheduleRetry(request); // Retry with backoff
}const RETRYABLE_ERRORS = [
'PP_MIDD_018', // Server down
'PP_MIDD_019', // Downstream error
'PPCUST_007', // Service unavailable
'PP_CORP_022', // Service unavailable
];
async function retryWithBackoff(request, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await makeRequest(request);
} catch (error) {
if (!RETRYABLE_ERRORS.includes(error.businessCode)
|| i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000); // 1s, 2s, 4s
}
}
}const USER_MESSAGES = {
'PP_MIDD_003': 'Invalid PAN format. Use: ABCDE1234F',
'PP_MIDD_016': 'Account locked for 24 hours due to failed attempts.',
'PP_MIDD_035': 'Yearly wallet limit exceeded.',
'PPCUST_079': 'Insufficient balance. Please add funds.',
'PPCUST_105': 'Card is not active. Please activate first.',
'PP_CORP_088': 'Customer already exists with these details.',
};
function getUserMessage(code, detail) {
return USER_MESSAGES[code] || detail || 'An error occurred.';
}Always log the full error response including business.code, detail, and path for debugging and support ticket resolution.
