Error Handling
Error responses, status codes, and error codes used by the Snippe API
{
"status": "success",
"code": 200,
"data": {
// Response data
}
}
{
"status": "error",
"code": 400,
"error_code": "VAL_001",
"message": "validation failed: email is required"
}
| Code | Name | Description |
|---|
| 200 | OK | Request successful |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request (validation errors, malformed JSON) |
| 401 | Unauthorized | Authentication required or failed |
| 403 | Forbidden | Authenticated but not authorized |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Resource already exists or state conflict |
| 422 | Unprocessable Entity | Idempotency key mismatch |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side error |
| 503 | Service Unavailable | External service temporarily down |
Error codes follow the pattern PREFIX_NNN where the prefix indicates the category.
| Code | Description | Common Cause |
|---|
AUTH_001 | Unauthorized | No authentication provided |
AUTH_002 | Invalid token | Malformed or corrupted JWT |
AUTH_003 | Token expired | JWT past expiration time |
AUTH_004 | Invalid credentials | Wrong email/password |
AUTH_005 | Missing auth header | Authorization header not sent |
AUTH_006 | Invalid auth header | Malformed authorization header |
AUTH_007 | Invalid API key | API key format or validation failed |
AUTH_008 | API key expired | API key past expiration date |
AUTH_009 | Invalid refresh token | Refresh token invalid or expired |
| Code | Description | Common Cause |
|---|
AUTHZ_001 | Forbidden | Access denied to resource |
AUTHZ_002 | Insufficient scope | API key lacks required scope |
AUTHZ_003 | Insufficient role | User role insufficient for operation |
| Code | Description | Common Cause |
|---|
VAL_001 | Validation failed | One or more fields invalid |
VAL_002 | Invalid request | Request body parsing failed |
VAL_003 | Missing field | Required field not provided |
VAL_004 | Invalid format | Field format doesn't match expected |
VAL_005 | Invalid amount | Amount outside allowed range |
VAL_006 | Invalid currency | Currency code not supported |
VAL_007 | Invalid OTP | Wrong OTP code entered |
VAL_008 | OTP expired | OTP expired or too many attempts |
| Code | HTTP | Description |
|---|
RES_001 | 404 | Resource not found |
RES_002 | 409 | Resource already exists |
RES_003 | 409 | State conflict |
| Code | Description | Common Cause |
|---|
PAY_001 | Payment failed | PSP processing error |
PAY_002 | Payment expired | Payment window closed |
PAY_003 | Payment cancelled | User or system cancelled |
PAY_004 | Insufficient funds | User balance too low |
PAY_005 | Transfer failed | Fund transfer failed |
| Code | Description |
|---|
INT_001 | Internal error |
INT_002 | Database error |
INT_003 | External service error |
INT_004 | Service unavailable |
| Code | Description |
|---|
RATE_001 | Rate limit exceeded |
{
"status": "error",
"code": 400,
"error_code": "VAL_002",
"message": "invalid request body"
}
Fix: Ensure you're sending valid JSON with correct Content-Type header.
{
"status": "error",
"code": 400,
"error_code": "VAL_001",
"message": "validation failed: amount is required, phone_number is required"
}
{
"status": "error",
"code": 400,
"error_code": "VAL_004",
"message": "validation failed: phone_number must be a valid phone number"
}
Fix: Use format +255XXXXXXXXX or 255XXXXXXXXX.
{
"status": "error",
"code": 400,
"error_code": "VAL_005",
"message": "amount 100 is below minimum of 500"
}
{
"status": "error",
"code": 403,
"error_code": "AUTHZ_002",
"message": "API key does not have required scope: disbursement:create"
}
Fix: Create a new API key with the required scope.
{
"status": "error",
"code": 422,
"error_code": "VAL_001",
"message": "idempotency key already used with different request body"
}
Fix: Use a unique idempotency key for each unique request.
| Field | Rule |
|---|
| Minimum | 500 TZS (payments), 5,000 TZS (payouts) |
| Maximum | Varies by account type |
| Format | Integer (smallest currency unit) |
| Format | Example |
|---|
| With country code | +255712345678 |
| Without plus | 255712345678 |
| Supported | Code |
|---|
| Tanzanian Shilling | TZS |
- Must be valid HTTPS URLs
- Maximum 500 characters
- Used for:
webhook_url, redirect_url, cancel_url