Errors
Understanding and handling Shika Creators API errors.
Errors
Shika Creators uses conventional HTTP response codes to indicate the success or failure of an API request. Codes in the 2xx range indicate success, 4xx codes indicate an error from the information provided, and 5xx codes indicate a server error.
Error Response Format
All errors follow this format:
{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "The amount must be a positive integer",
"param": "amount",
"doc_url": "https://docs.shikacreators.com/errors/parameter_invalid"
}
}Error Object
| Field | Type | Description |
|---|---|---|
type | string | The type of error |
code | string | Specific error code |
message | string | Human-readable message |
param | string | Parameter that caused the error (if applicable) |
doc_url | string | Link to documentation about this error |
HTTP Status Codes
| Status | Description |
|---|---|
200 | OK - Request succeeded |
201 | Created - Resource created successfully |
400 | Bad Request - Invalid parameters |
401 | Unauthorized - Invalid API key |
403 | Forbidden - Not allowed to access resource |
404 | Not Found - Resource doesn't exist |
409 | Conflict - Request conflicts with current state |
422 | Unprocessable Entity - Request understood but cannot be processed |
429 | Too Many Requests - Rate limit exceeded |
500 | Internal Server Error - Something went wrong on our end |
Error Types
api_error
Server-side errors. These are rare and indicate something went wrong on Shika Creators's end.
{
"error": {
"type": "api_error",
"message": "An unexpected error occurred. Please try again."
}
}authentication_error
Invalid or missing API key.
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Invalid API key provided."
}
}invalid_request_error
The request has invalid parameters.
{
"error": {
"type": "invalid_request_error",
"code": "parameter_missing",
"message": "Missing required parameter: amount",
"param": "amount"
}
}rate_limit_error
Too many requests in a short period.
{
"error": {
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "Too many requests. Please retry after 60 seconds."
}
}card_error
Card payment-specific errors.
{
"error": {
"type": "card_error",
"code": "payment_method_declined",
"message": "The card was declined."
}
}idempotency_error
Conflicting idempotency key errors.
{
"error": {
"type": "idempotency_error",
"code": "idempotent_request_mismatch",
"message": "The request body does not match the original request with this idempotency key."
}
}Error Codes
Authentication Errors
| Code | Status | Description |
|---|---|---|
invalid_api_key | 401 | The API key is invalid |
api_key_expired | 401 | The API key has expired |
missing_api_key | 401 | No API key provided |
invalid_token | 401 | The authentication token is invalid |
token_expired | 401 | The authentication token has expired |
access_denied | 403 | You do not have permission to perform this action |
insufficient_permissions | 403 | Your API key does not have the required permissions |
secret_key_required | 403 | This endpoint requires a secret API key (sk_*) |
live_mode_required | 403 | This action can only be performed in live mode |
test_mode_required | 403 | This action can only be performed in test mode |
two_factor_required | 403 | Two-factor authentication is required |
Request Errors
| Code | Status | Description |
|---|---|---|
invalid_request | 400 | The request was invalid |
missing_required_param | 400 | A required parameter is missing |
invalid_param | 400 | A parameter value is invalid |
invalid_phone_number | 400 | The phone number is invalid |
invalid_email | 400 | The email address is invalid |
invalid_amount | 400 | The amount is invalid |
invalid_provider | 400 | The payment provider is not supported |
invalid_metadata | 400 | The metadata is invalid |
metadata_limit_exceeded | 400 | The metadata exceeds the maximum allowed size |
resource_not_found | 404 | Requested resource doesn't exist |
resource_already_exists | 409 | A resource with this identifier already exists |
customer_already_exists | 409 | A customer with this email or phone already exists |
duplicate_coupon_code | 409 | A coupon with this code already exists |
Idempotency Errors
| Code | Status | Description |
|---|---|---|
idempotency_key_in_use | 409 | A request with this idempotency key is already being processed |
idempotent_request_mismatch | 409 | The request body does not match the original request |
Amount Errors
| Code | Status | Description |
|---|---|---|
amount_too_small | 400 | Below minimum (GHS 1.00) |
amount_too_large | 400 | Above maximum allowed |
invalid_currency | 400 | Currency not supported |
State Errors
| Code | Status | Description |
|---|---|---|
invalid_state_transition | 400 | The requested state transition is not allowed |
payment_already_completed | 400 | This payment has already been completed |
payment_already_refunded | 400 | This payment has already been refunded |
payment_cannot_be_refunded | 400 | This payment cannot be refunded in its current state |
refund_amount_exceeds_payment | 400 | The refund amount exceeds the original payment amount |
subscription_already_canceled | 400 | This subscription has already been canceled |
invoice_already_paid | 400 | This invoice has already been paid |
invoice_already_finalized | 400 | This invoice has already been finalized |
dispute_already_closed | 400 | This dispute has already been closed |
evidence_already_submitted | 400 | Evidence has already been submitted for this dispute |
evidence_deadline_passed | 400 | The deadline for submitting evidence has passed |
Balance & Limit Errors
| Code | Status | Description |
|---|---|---|
insufficient_balance | 400 | Insufficient balance to complete this transaction |
daily_limit_exceeded | 400 | Daily transaction limit exceeded |
monthly_limit_exceeded | 400 | Monthly transaction limit exceeded |
transaction_count_exceeded | 400 | Transaction count limit exceeded |
Payment Provider Errors
| Code | Status | Description |
|---|---|---|
payment_failed | 402 | The payment could not be processed |
insufficient_funds | 402 | The account has insufficient funds |
payment_method_declined | 402 | The payment method was declined |
account_not_found | 402 | The payment account was not found |
provider_error | 502 | The payment provider returned an error |
provider_timeout | 504 | The payment provider did not respond in time |
provider_unavailable | 503 | The payment provider is currently unavailable |
Fraud & Security Errors
| Code | Status | Description |
|---|---|---|
payment_blocked | 403 | This payment has been blocked due to suspected fraud |
high_risk_transaction | 403 | This transaction has been flagged as high risk |
blocklisted | 403 | This account or identifier is on the blocklist |
velocity_exceeded | 403 | Too many transactions in a short period |
File Upload Errors
| Code | Status | Description |
|---|---|---|
file_too_large | 400 | The file exceeds the maximum allowed size |
invalid_file_type | 400 | The file type is not supported |
file_upload_failed | 500 | The file could not be uploaded |
Webhook Errors
| Code | Status | Description |
|---|---|---|
invalid_webhook_url | 400 | The webhook URL is invalid (must be HTTPS) |
invalid_webhook_signature | 400 | The webhook signature is invalid |
Rate Limit Errors
| Code | Status | Description |
|---|---|---|
rate_limit_exceeded | 429 | Too many requests |
Server Errors
| Code | Status | Description |
|---|---|---|
internal_error | 500 | An internal error occurred |
service_unavailable | 503 | The service is temporarily unavailable |
Handling Errors
import Shika Creators, { Shika CreatorsError } from '@shikacreators/node'
const shikacreators = new Shika Creators('sk_test_...')
try {
const payment = await shikacreators.payments.create({
amount: 5000,
currency: 'GHS',
payment_method: 'mobile_money',
phone: '0241234567'
})
} catch (error) {
if (error instanceof Shika CreatorsError) {
switch (error.type) {
case 'authentication_error':
console.error('Check your API key')
break
case 'invalid_request_error':
console.error(`Invalid parameter: ${error.param}`)
break
case 'payment_error':
switch (error.code) {
case 'insufficient_funds':
// Tell customer to top up
break
case 'phone_unreachable':
// Tell customer to check their phone
break
default:
console.error(error.message)
}
break
case 'rate_limit_error':
// Wait and retry
await sleep(60000)
break
case 'api_error':
// Log and alert
console.error('Shika Creators server error:', error.message)
break
}
} else {
// Network error or other
console.error('Unexpected error:', error)
}
}import shikacreators
from shikacreators.errors import (
Shika CreatorsError,
AuthenticationError,
InvalidRequestError,
PaymentError,
RateLimitError,
APIError
)
client = shikacreators.Client('sk_test_...')
try:
payment = client.payments.create(
amount=5000,
currency='GHS',
payment_method='mobile_money',
phone='0241234567'
)
except AuthenticationError as e:
print('Check your API key')
except InvalidRequestError as e:
print(f'Invalid parameter: {e.param}')
except PaymentError as e:
if e.code == 'insufficient_funds':
print('Please top up your account')
elif e.code == 'phone_unreachable':
print('Please check your phone')
else:
print(e.message)
except RateLimitError:
import time
time.sleep(60)
# Retry
except APIError as e:
print(f'Shika Creators server error: {e.message}')
except Shika CreatorsError as e:
print(f'Error: {e.message}')use Shika Creators\Shika Creators;
use Shika Creators\Exception\Shika CreatorsException;
use Shika Creators\Exception\AuthenticationException;
use Shika Creators\Exception\InvalidRequestException;
use Shika Creators\Exception\PaymentException;
use Shika Creators\Exception\RateLimitException;
use Shika Creators\Exception\ApiException;
$shikacreators = new Shika Creators('sk_test_...');
try {
$payment = $shikacreators->payments->create([
'amount' => 5000,
'currency' => 'GHS',
'payment_method' => 'mobile_money',
'phone' => '0241234567'
]);
} catch (AuthenticationException $e) {
echo 'Check your API key';
} catch (InvalidRequestException $e) {
echo 'Invalid parameter: ' . $e->getParam();
} catch (PaymentException $e) {
switch ($e->getCode()) {
case 'insufficient_funds':
echo 'Please top up your account';
break;
case 'phone_unreachable':
echo 'Please check your phone';
break;
default:
echo $e->getMessage();
}
} catch (RateLimitException $e) {
sleep(60);
// Retry
} catch (ApiException $e) {
error_log('Shika Creators server error: ' . $e->getMessage());
} catch (Shika CreatorsException $e) {
echo 'Error: ' . $e->getMessage();
}Best Practices
1. Always Handle Errors
Never assume API calls will succeed:
// Bad - no error handling
const payment = await shikacreators.payments.create({...})
// Good - proper error handling
try {
const payment = await shikacreators.payments.create({...})
} catch (error) {
// Handle appropriately
}2. Show Helpful Messages
Map error codes to user-friendly messages:
const errorMessages = {
insufficient_funds: 'Your mobile money balance is too low. Please top up and try again.',
phone_unreachable: 'We couldn\'t reach your phone. Make sure it\'s on and try again.',
timeout: 'The request timed out. Please try again.',
daily_limit_exceeded: 'You\'ve reached your daily limit. Try again tomorrow.'
}
function getErrorMessage(error) {
return errorMessages[error.code] || 'Something went wrong. Please try again.'
}3. Log Errors for Debugging
Log errors with context for debugging:
catch (error) {
console.error('Payment failed', {
type: error.type,
code: error.code,
message: error.message,
param: error.param,
requestId: error.requestId,
orderId: order.id
})
}4. Retry Intelligently
Implement retries with exponential backoff for transient errors:
async function createPaymentWithRetry(params, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await shikacreators.payments.create(params)
} catch (error) {
if (error.type === 'api_error' && i < maxRetries - 1) {
await sleep(Math.pow(2, i) * 1000) // 1s, 2s, 4s
continue
}
throw error
}
}
}Only retry on transient errors like api_error or rate_limit_error. Don't retry on invalid_request_error or payment_error.