Mockupanda
API Documentation
Back to app

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_KEYNo Authorization header
401INVALID_API_KEYKey is wrong or revoked
402INSUFFICIENT_CREDITSWallet balance too low
400MISSING_TEMPLATE_IDtemplate_id not provided
404TEMPLATE_NOT_FOUNDTemplate ID doesn't exist
400MISSING_ARTWORKNo artwork file or URL
400INVALID_ARTWORK_URLURL is not valid http/https
400IMAGE_URL_NOT_FOUNDArtwork URL returned 404
413ARTWORK_FILE_TOO_LARGEFile exceeds 20 MB limit
408IMAGE_FETCH_TIMEOUTDownload timed out

Common 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.jpg

ARTWORK_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.jpg

IMAGE_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:

  1. Check the error code and details fields
  2. Review the API changelog
  3. 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.

Next Steps