Error Handling
The Mockupanda API uses standard HTTP status codes and returns detailed error messages in JSON format. This page covers all error codes, how to handle them, and best practices.
Error Response Format
All errors return JSON with this structure:
{
"error": "Human-readable error message",
"code": "MACHINE_READABLE_ERROR_CODE",
"details": { /* Optional additional context */ },
"hint": "Optional suggestion for fixing the error"
}Example Error
{
"error": "Insufficient account balance. Add funds in Billing to continue.",
"code": "INSUFFICIENT_CREDITS",
"details": {
"required_cents": 1,
"balance_cents": 0
},
"hint": "Top up your API wallet from Dashboard > Billing and retry."
}HTTP Status Codes
| Status | Meaning | Action |
|--------|---------|--------|
| 200 | Success | Process the response |
| 400 | Bad Request | Fix request parameters |
| 401 | Unauthorized | Check API key |
| 402 | Payment Required | Add credits to wallet |
| 404 | Not Found | Verify template ID exists |
| 408 | Timeout | Retry with shorter timeout |
| 413 | Payload Too Large | Reduce artwork file size |
| 429 | Too Many Requests | Implement rate limiting |
| 500 | Internal Server Error | Retry with exponential backoff |
Error Codes
{
"error": "Insufficient account balance. Add funds in Billing to continue.",
"code": "INSUFFICIENT_CREDITS",
"details": { "required_cents": 1, "balance_cents": 0 },
"hint": "Top up your API wallet from Dashboard > Billing and retry."
}401MISSING_API_KEY— No Authorization header401INVALID_API_KEY— Key is wrong or revoked402INSUFFICIENT_CREDITS— Wallet balance too low400MISSING_TEMPLATE_ID— template_id not provided404TEMPLATE_NOT_FOUND— Template ID doesn't exist400MISSING_ARTWORK— No artwork file or URL400INVALID_ARTWORK_URL— URL is not valid http/https400IMAGE_URL_NOT_FOUND— Artwork URL returned 404413ARTWORK_FILE_TOO_LARGE— File exceeds 20 MB limit408IMAGE_FETCH_TIMEOUT— Download timed outCommon Errors
Authentication Errors
MISSING_API_KEY
{
"error": "Authorization header is required",
"code": "MISSING_API_KEY"
}Cause: No Authorization header in request.
Fix: Add the header:
-H "Authorization: Bearer YOUR_API_KEY"INVALID_API_KEY
{
"error": "Invalid or revoked API key",
"code": "INVALID_API_KEY"
}Cause: API key is incorrect, expired, or revoked.
Fix: Verify your API key in Dashboard → API Keys. Generate a new key if needed.
Payment Errors
INSUFFICIENT_CREDITS
{
"error": "Insufficient account balance. Add funds in Billing to continue.",
"code": "INSUFFICIENT_CREDITS",
"details": {
"required_cents": 1,
"balance_cents": 0
},
"hint": "Top up your API wallet from Dashboard > Billing and retry."
}Cause: Your wallet doesn't have enough credits.
Fix: Add credits at Dashboard → Billing. Each mockup costs 1 credit ($0.01 USD).
Template Errors
MISSING_TEMPLATE_ID
{
"error": "template_id is required",
"code": "MISSING_TEMPLATE_ID"
}Cause: No template_id parameter in request.
Fix: Add the template_id parameter:
-F "template_id=bedroom-poster-01"TEMPLATE_NOT_FOUND
{
"error": "Template not found",
"code": "TEMPLATE_NOT_FOUND",
"details": {
"template_id": "invalid-id"
}
}Cause: Template ID doesn't exist.
Fix: Verify the template ID exists at mockupanda.com/editor or via the templates endpoint.
Artwork Errors
MISSING_ARTWORK
{
"error": "artwork_url or artwork_urls is required",
"code": "MISSING_ARTWORK"
}Cause: No artwork URL provided.
Fix: Add either artwork_url (single-frame) or artwork_urls (multi-frame):
-F "artwork_url=https://example.com/art.jpg"INVALID_ARTWORK_URL
{
"error": "Artwork URL must be a valid HTTP or HTTPS URL",
"code": "INVALID_ARTWORK_URL"
}Cause: URL is malformed or uses an unsupported protocol.
Fix: Ensure the URL starts with http:// or https://:
-F "artwork_url=https://example.com/art.jpg"IMAGE_URL_NOT_FOUND
{
"error": "Failed to fetch artwork from URL (404 Not Found)",
"code": "IMAGE_URL_NOT_FOUND"
}Cause: The artwork URL returned a 404 error.
Fix: Verify the URL is publicly accessible:
curl -I https://example.com/art.jpgARTWORK_FILE_TOO_LARGE
{
"error": "Artwork file is too large (max 20 MB)",
"code": "ARTWORK_FILE_TOO_LARGE"
}Cause: Artwork file exceeds 20 MB limit.
Fix: Compress or resize the artwork:
# Using ImageMagick
convert input.jpg -quality 85 -resize 3000x3000 output.jpgIMAGE_FETCH_TIMEOUT
{
"error": "Failed to download artwork within 10 seconds",
"code": "IMAGE_FETCH_TIMEOUT"
}Cause: Artwork URL took too long to respond.
Fix: Use a CDN or faster hosting for artwork files.
Rate Limit Errors
RATE_LIMIT_EXCEEDED
{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"details": {
"limit": 100,
"window": "60s",
"retry_after": 23
}
}Cause: Too many requests in a short time.
Fix: Wait retry_after seconds before retrying. Implement rate limiting in your code (see below).
Error Handling Best Practices
Retry Logic
Implement exponential backoff for transient errors:
async function generateMockupWithRetry(params, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await generateMockup(params);
return response;
} catch (error) {
// Retry on 408, 429, 500+ errors
if ([408, 429, 500, 502, 503, 504].includes(error.status)) {
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
await sleep(delay);
continue;
}
// Don't retry on client errors (400, 401, 402, 404, 413)
throw error;
}
}
throw new Error('Max retries exceeded');
}Rate Limiting
Respect the API's rate limits:
const RATE_LIMIT = 100; // requests per minute
const WINDOW_MS = 60 * 1000; // 60 seconds
let requestCount = 0;
let windowStart = Date.now();
async function rateLimitedRequest(params) {
const now = Date.now();
if (now - windowStart >= WINDOW_MS) {
// Reset window
requestCount = 0;
windowStart = now;
}
if (requestCount >= RATE_LIMIT) {
const waitMs = WINDOW_MS - (now - windowStart);
await sleep(waitMs);
requestCount = 0;
windowStart = Date.now();
}
requestCount++;
return await generateMockup(params);
}Error Logging
Log errors with context for debugging:
try {
const response = await generateMockup(params);
} catch (error) {
console.error('Mockup generation failed:', {
code: error.code,
message: error.error,
details: error.details,
params: params,
timestamp: new Date().toISOString()
});
throw error;
}User-Friendly Messages
Translate error codes into user-friendly messages:
const ERROR_MESSAGES = {
INSUFFICIENT_CREDITS: 'Your account balance is too low. Please add credits.',
INVALID_API_KEY: 'Invalid API key. Please check your configuration.',
TEMPLATE_NOT_FOUND: 'The selected template is no longer available.',
ARTWORK_FILE_TOO_LARGE: 'Your artwork file is too large. Please use a smaller image.',
RATE_LIMIT_EXCEEDED: 'Too many requests. Please try again in a moment.'
};
function getUserMessage(errorCode) {
return ERROR_MESSAGES[errorCode] || 'An unexpected error occurred. Please try again.';
}Graceful Degradation
Handle errors gracefully in your application:
async function generateMockupSafely(params) {
try {
return await generateMockup(params);
} catch (error) {
if (error.code === 'INSUFFICIENT_CREDITS') {
// Redirect to billing page
window.location.href = '/billing';
} else if (error.code === 'TEMPLATE_NOT_FOUND') {
// Fallback to default template
params.template_id = 'bedroom-poster-01';
return await generateMockup(params);
} else {
// Show error to user
showError(getUserMessage(error.code));
return null;
}
}
}Monitoring
Monitor error rates to detect issues early:
const errorMetrics = {
total: 0,
byCode: {}
};
function trackError(error) {
errorMetrics.total++;
errorMetrics.byCode[error.code] = (errorMetrics.byCode[error.code] || 0) + 1;
// Alert if error rate exceeds threshold
if (errorMetrics.total > 100) {
console.warn('High error rate detected:', errorMetrics);
}
}Support
If you encounter an error not documented here:
- Check the error
codeanddetailsfields - Review the API changelog
- Contact support via the feedback button in your dashboard
Include the full error response and your request parameters (without your API key) for faster resolution.