API Integration Best Practices
Build robust API integrations. Implement parallel processing, retry logic, and error handling.

TL;DR
Build robust API integrations: use retry logic with exponential backoff, implement parallel processing for batch operations, handle rate limits gracefully, and log all API interactions for debugging.
Key Takeaways:
- •Implement retry logic with exponential backoff
- •Use parallel processing for batch operations
- •Handle rate limits with queue management
- •Log all API calls for debugging and monitoring
Building robust API integrations means handling limits and errors gracefully. This guide covers best practices for parallel processing, retry logic, and error handling - so your mockup pipeline never breaks.
Understanding Parallel Limits
SudoMock uses parallel limits to ensure fair usage and consistent performance. These limits determine how many simultaneous requests you can have in-flight at once:
| Plan | Parallel Renders | Parallel Uploads |
|---|---|---|
| Free | 1 | 1 |
| Starter | 3 | 2 |
| Pro | 10 | 5 |
| Scale | 25 | 10 |
Response Headers
Every API response includes parallel limit headers:
x-concurrent-limit- Your parallel limitx-concurrent-remaining- Available slotsRetry-After- Seconds to wait (only on 429 responses)
Handling 429 Errors
When you exceed parallel limits, the API returns 429 Parallel Limit Reached.
Here's how to handle it properly:
1async function renderWithRetry(payload, maxRetries = 3) {2 for (let attempt = 0; attempt < maxRetries; attempt++) {3 const response = await fetch('https://api.sudomock.com/api/v1/renders', {4 method: 'POST',5 headers: {6 'X-API-KEY': API_KEY,7 'Content-Type': 'application/json'8 },9 body: JSON.stringify(payload)10 });1112 if (response.ok) {13 return response.json();14 }1516 if (response.status === 429) {17 // Get retry delay from header, or use short backoff18 const retryAfter = response.headers.get('Retry-After');19 const delay = retryAfter20 ? parseInt(retryAfter) * 100021 : Math.pow(2, attempt) * 1000;2223 console.log(`Parallel limit reached. Retrying in \${delay}ms...`);24 await sleep(delay);25 continue;26 }2728 // Other errors - don't retry29 throw new Error(`API error: \${response.status}`);30 }3132 throw new Error('Max retries exceeded');33}3435function sleep(ms) {36 return new Promise(resolve => setTimeout(resolve, ms));37}
Exponential Backoff
For retry logic, exponential backoff prevents overwhelming the API. The delay doubles with each retry attempt:
1function getBackoffDelay(attempt, baseDelay = 1000) {2 // Exponential: 1s, 2s, 4s, 8s...3 const exponentialDelay = Math.pow(2, attempt) * baseDelay;45 // Add jitter (0-25% random) to prevent thundering herd6 const jitter = exponentialDelay * Math.random() * 0.25;78 // Cap at 30 seconds9 return Math.min(exponentialDelay + jitter, 30000);10}
Why Jitter?
When multiple clients hit limits simultaneously, they all retry at the same time - causing another limit breach. Adding random jitter spreads out retries.
Parallel Processing Strategy
For high-volume workloads, process requests in parallel up to your plan's limit:
1class ParallelQueue {2 constructor(parallelLimit) {3 this.queue = [];4 this.activeCount = 0;5 this.parallelLimit = parallelLimit;6 this.results = [];7 }89 async add(payload) {10 return new Promise((resolve, reject) => {11 this.queue.push({ payload, resolve, reject });12 this.process();13 });14 }1516 async process() {17 while (this.queue.length > 0 && this.activeCount < this.parallelLimit) {18 const { payload, resolve, reject } = this.queue.shift();19 this.activeCount++;2021 renderWithRetry(payload)22 .then(result => {23 resolve(result);24 this.activeCount--;25 this.process(); // Process next in queue26 })27 .catch(error => {28 reject(error);29 this.activeCount--;30 this.process();31 });32 }33 }34}3536// Usage: 10 parallel renders on Pro plan37const queue = new ParallelQueue(10);3839// Add 100 renders - they'll process 10 at a time40for (const design of designs) {41 queue.add({ mockup_uuid, smart_objects: [{ uuid: soId, asset: { url: design } }] })42 .then(result => console.log('Done:', result))43 .catch(err => console.error('Failed:', err));44}
Error Types & Handling
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Process result |
| 400 | Bad request | Fix payload, don't retry |
| 401 | Unauthorized | Check API key |
| 404 | Not found | Check mockup UUID |
| 429 | Parallel limit reached | Retry with backoff |
| 500 | Server error | Retry with backoff |
Don't Retry Everything
Only retry 429 and 5xx errors. Client errors like 400
and 401 won't succeed on retry - fix the underlying issue instead.
Monitoring & Metrics
Track these metrics to optimize your API usage:
Best Practice
Use the x-concurrent-remaining header proactively. If it's getting low,
wait for active requests to complete before sending more.
Related Resources
Frequently Asked Questions
Related Articles

SudoMock Now Works with Claude, Cursor, ChatGPT, and Any MCP-Compatible AI Tool
Render product mockups directly from any AI assistant that supports MCP. Claude, Cursor, VS Code, ChatGPT, Windsurf, and more.

Understanding Mockup API Data Models: A Technical Guide
Deep dive into mockup API response structures. Learn how smart object data is organized, what each field means, and how to build robust integrations.
Explore by Use Case
See SudoMock in action for your specific product category
Your own PSD, rendered via API
Render your own PSD through the API. Start with 500 one-time credits, no card.