Error Handling
Error responses, status codes, and error codes used by the Snippe API
All API errors follow a consistent format to help you handle them gracefully.
Response Format
{
"status": "success",
"code": 200,
"data": {
// Response data
}
}{
"status": "error",
"code": 400,
"error_code": "validation_error",
"message": "amount is required"
}HTTP Status Codes
| 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 |
Common Error Scenarios
Invalid API Key (401)
{
"status": "error",
"code": 401,
"error_code": "unauthorized",
"message": "invalid or missing API key"
}Fix: Check that your API key is correct and included in the
Authorization header.
Insufficient Scope (403)
{
"status": "error",
"code": 403,
"error_code": "insufficient_scope",
"message": "API key does not have required scope: disbursement:create"
}Fix: Create a new API key with the required scope from the Dashboard.
Missing Required Fields (400)
{
"status": "error",
"code": 400,
"error_code": "validation_error",
"message": "amount is required"
}Invalid Phone Number (400)
{
"status": "error",
"code": 400,
"error_code": "validation_error",
"message": "phone_number must be a valid phone number"
}Fix: Use format 255XXXXXXXXX or +255XXXXXXXXX for Tanzanian numbers.
Amount Out of Range (400)
{
"status": "error",
"code": 400,
"error_code": "validation_error",
"message": "amount 100 is below minimum of 500"
}Payment Not Found (404)
{
"status": "error",
"code": 404,
"error_code": "not_found",
"message": "payment not found"
}Insufficient Balance (500)
{
"status": "error",
"code": 500,
"error_code": "payment_failed",
"message": "insufficient balance: available 5000, required 6500"
}Fix: Top up your account balance before creating payouts.
Idempotency Conflict (422)
{
"status": "error",
"code": 422,
"error_code": "validation_error",
"message": "idempotency key already used with different request body"
}Fix: Use a unique idempotency key for each unique request.
Payment Processor Unavailable (500)
{
"status": "error",
"code": 500,
"error_code": "PAY_001",
"message": "failed to initiate payment"
}Note: This error is returned for both transient processor outages and when the Idempotency-Key exceeds 30 characters. If you see this error, first check that your idempotency key is 30 characters or fewer, then retry with exponential backoff for processor issues.
Rate Limit Exceeded (429)
{
"status": "error",
"code": 429,
"error_code": "rate_limit_exceeded",
"message": "Too many requests"
}Fix: Implement exponential backoff and respect the X-Ratelimit-Reset header.
Error Codes Reference
Authentication Errors
| Code | Description |
|---|---|
unauthorized | Invalid or missing API key |
insufficient_scope | API key lacks required scope |
Validation Errors
| Code | Description |
|---|---|
validation_error | One or more fields invalid |
Resource Errors
| Code | Description |
|---|---|
not_found | Resource doesn't exist |
conflict | Resource state conflict |
Payment Errors
| Code | Description |
|---|---|
payment_failed | Payment processing error |
PAY_001 | Failed to initiate payment — returned when the payment processor (Selcom/evmak) is temporarily unavailable or when the Idempotency-Key exceeds the 30-character limit |
Validation Rules
| Rule | Value |
|---|---|
| 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 |
Phone numbers must be valid Tanzanian mobile numbers.
- Must be valid HTTPS URLs
- Maximum 500 characters
- Used for:
webhook_url,redirect_url,cancel_url
Best Practices
Log All Errors Log the full error response including error_code and
message for debugging.
Implement Retries For 5xx errors and network failures, implement
exponential backoff.