How to Handle Rate Limiting When Using APIMart: A Complete Guide
When APIMart returns HTTP 429, the SDK translates it into a APIMART_RATE_LIMITED error that includes a retryAfterMs property, allowing you to pause and retry automatically.
The freestylefly/awesome-gpt-image-2 repository provides a robust JavaScript SDK for image generation through APIMart. Learning to handle rate limiting when using APIMart ensures your application remains responsive and avoids service disruptions when you hit per-key request quotas.
Understanding APIMart Rate Limits
APIMart enforces strict per-key request quotas to ensure fair usage across all clients. When you exceed your allocated limit, the API responds with HTTP 429 (Too Many Requests). The SDK in this repository transforms these responses into structured errors that contain actionable retry information.
Detecting Rate Limit Errors
The SDK identifies rate-limit conditions through the apimartErrorCode utility found in shared/apimart.js. At line 73, this function maps HTTP 429 responses to the constant APIMART_RATE_LIMITED, creating a standardized error object you can catch reliably.
// Error detection happens automatically
if (error.code === 'APIMART_RATE_LIMITED') {
console.log('Rate limit exceeded');
}
Reading the Retry-After Interval
Every rate-limit response includes a Retry-After header indicating how long to wait before retrying. The retryAfterMilliseconds helper (lines 81–90 in shared/apimart.js) parses this header—whether it contains seconds or a timestamp—and attaches the value to error.retryAfterMs as a millisecond integer.
// The error object includes the wait time
const waitTime = error.retryAfterMs || 2000; // fallback to 2 seconds
Automatic Retry Mechanisms in the SDK
The repository implements intelligent back-off logic directly in the polling utilities, reducing the boilerplate required in your application code.
The pollApimartTask Function
The pollApimartTask function in src/apimartClient.js (lines 44–46) automatically catches APIMART_RATE_LIMITED errors during status polling. When this occurs, the function pauses execution for the duration specified in error.retryAfterMs before attempting the next poll, ensuring you never exceed the API's suggested retry rate.
import { pollApimartTask, fetchPersonalTask } from './src/apimartClient.js';
async function waitForCompletion(taskId, apiKey) {
const fetchTask = () => fetchPersonalTask(taskId, apiKey, 'en');
// Automatically handles 429 errors with proper delays
const result = await pollApimartTask(fetchTask, {
intervalMs: 3000,
maxAttempts: 120
});
return result;
}
Implementing Rate Limit Handling
While the SDK handles polling retries automatically, generation submissions and other direct API calls require explicit error handling in your application layer.
Basic Error Handling Pattern
Wrap your submission calls in try-catch blocks that specifically check for APIMART_RATE_LIMITED. Use the retryAfterMs property to delay your retry attempt.
import {
submitPersonalGeneration,
verifyPersonalApimartKey
} from './src/apimartClient.js';
async function generateImage(prompt, apiKey) {
try {
await verifyPersonalApimartKey(apiKey);
const { taskId } = await submitPersonalGeneration(prompt, apiKey, 'en');
return taskId;
} catch (err) {
if (err.code === 'APIMART_RATE_LIMITED') {
console.warn(`Rate limited. Retry after ${err.retryAfterMs}ms`);
await new Promise(res => setTimeout(res, err.retryAfterMs));
return generateImage(prompt, apiKey); // Retry once
}
throw err;
}
}
Exponential Backoff for Batch Processing
When submitting multiple generations in sequence, implement exponential backoff to prevent hammering the API. Start with a base delay and double the wait time after each consecutive rate-limit error, capping at 60 seconds.
import { submitPersonalGeneration } from './src/apimartClient.js';
async function submitWithBackoff(prompt, apiKey) {
let backoff = 2000; // 2 seconds initial
for (let attempt = 0; attempt < 5; attempt++) {
try {
return await submitPersonalGeneration(prompt, apiKey, 'en');
} catch (e) {
if (e.code !== 'APIMART_RATE_LIMITED') throw e;
const waitMs = e.retryAfterMs || backoff;
console.log(`Attempt ${attempt + 1} rate limited. Waiting ${waitMs}ms`);
await new Promise(r => setTimeout(r, waitMs));
backoff = Math.min(60000, backoff * 2); // Cap at 60 seconds
}
}
throw new Error('Max retries exceeded due to rate limiting');
}
Best Practices for Production Use
Follow these guidelines to maintain optimal performance when interacting with APIMart:
- Respect
retryAfterMs: Never retry faster than the interval supplied by the API. ThepollApimartTaskimplementation insrc/apimartClient.jsalready adheres to this constraint. - Secure API Key Storage: The SDK stores keys under
APIMART_KEY_STORAGE_KEY. Ensure this storage mechanism meets your application's security requirements. - Monitor Rate Limit Headers: Although the SDK abstracts the
Retry-Afterheader, you can extendfetchImplto logX-RateLimit-LimitandX-RateLimit-Remainingfor capacity planning. - Graceful UI Feedback: Surface user-friendly messages like "Please wait a moment before generating another image" when catching
APIMART_RATE_LIMITEDin frontend applications. - Abort Handling: When users navigate away during polling, catch
APIMART_POLL_ABORTEDerrors (lines 99–105 insrc/apimartClient.js) to clean up UI state properly.
Summary
- APIMart returns HTTP 429 when exceeding per-key quotas, which the SDK converts to
APIMART_RATE_LIMITEDerrors viaapimartErrorCodeinshared/apimart.js. - The
retryAfterMillisecondsfunction parses theRetry-Afterheader and attaches the value toerror.retryAfterMs. - Automatic handling:
pollApimartTaskautomatically pauses for the specified duration when encountering rate limits during polling loops. - Manual handling: Wrap
submitPersonalGenerationcalls in try-catch blocks and implement exponential backoff starting at 2 seconds, capped at 60 seconds. - Key files include
shared/apimart.jsfor error utilities andsrc/apimartClient.jsfor high-level API methods with built-in retry logic.
Frequently Asked Questions
What error code does APIMart return when I hit the rate limit?
When you exceed your request quota, APIMart returns HTTP 429. The SDK's apimartErrorCode function in shared/apimart.js translates this into the string APIMART_RATE_LIMITED, allowing you to detect rate limiting programmatically without checking status codes directly.
How do I know how long to wait before retrying a failed request?
The SDK automatically parses the Retry-After response header using the retryAfterMilliseconds function (lines 81–90 in shared/apimart.js). This value is exposed as error.retryAfterMs on the thrown error object. If the header is missing, implement a fallback delay of 2000 milliseconds.
Does the SDK handle retries automatically?
The pollApimartTask function in src/apimartClient.js handles retries automatically for polling operations, pausing for error.retryAfterMs before continuing. However, submission functions like submitPersonalGeneration require you to implement your own retry logic using the error handling patterns shown in the examples above.
Where is the API key stored in this library?
According to the source code in shared/apimart.js, the SDK references APIMART_KEY_STORAGE_KEY for persistent storage of credentials. Ensure this storage location is secure and never expose the key in client-side logs or error messages.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →