How APIMart Handles Image Generation Tasks in awesome-gpt-image-2
APIMart serves as the backend provider for image generation in awesome-gpt-image-2, orchestrating tasks through a three-layer architecture that separates shared utilities, server-side API handling, and client-side task management.
The awesome-gpt-image-2 repository by freestylefly integrates APIMart to power GPT-image-2 model generation through a robust TypeScript/JavaScript implementation. This architecture enables both platform-mediated and direct personal API key workflows while handling task lifecycle management, caching, and comprehensive error translation.
Three-Layer Architecture
The integration divides responsibilities across shared helpers, server middleware, and browser clients to ensure consistent behavior across environments.
Shared Utilities Layer
The foundation resides in shared/apimart.js, which exports pure functions usable in both Node.js and browser contexts. This module defines constants, payload builders, response normalizers, and pricing utilities that remain agnostic to the execution environment.
Server-Side API Layer
Located in api/_lib/apimart.js and consumed by api/generate-image.js, this layer manages secure communication with APIMart. It reads the APIMART_API_KEY environment variable, submits generation requests to https://api.apimart.ai/v1/images/generations, and stores task IDs in Supabase. The server returns 202 Accepted responses to clients and translates upstream errors into semantic public codes like UPSTREAM_BUSY or SERVER_NOT_CONFIGURED.
Client-Side Wrapper
The browser implementation in src/apimartClient.js offers dual operation modes: personal key (direct APIMart calls) and platform key (proxied through the server API). It persists API keys and task states in localStorage using keys gpt-image-2-apimart-key:v1, gpt-image-2-pending-tests:v1, and gpt-image-2-generated-tests:v1.
The Generation Workflow
Understanding how APIMart handles image generation tasks requires examining the request lifecycle from submission to completion.
Configuration and Initialization
The server determines APIMart availability through getApimartConfig() in api/_lib/apimart.js, which checks for the presence of process.env.APIMART_API_KEY. This boolean flag dictates whether the provider appears as "configured" in health checks.
Submitting Generation Tasks
Platform Mode (Server-Proxied):
- The client POSTs to
/api/generate-imagewith a payload containingcaseId,prompt, andlanguage. - The handler validates the prompt and reserves a usage slot in Supabase.
- It invokes
submitApimartGeneration(), which callsbuildApimartGenerationPayload()to construct the request body. - The function POSTs to APIMart's
/v1/images/generationsendpoint. extractApimartTaskId()normalizes the response, extracting the task identifier for storage in thegeneration_reservationstable.
Personal Mode (Direct Browser):
Users with their own APIMart credentials bypass the server entirely. The submitPersonalGeneration(prompt, apiKey, language) function in src/apimartClient.js constructs and submits the identical payload directly from the browser to the APIMart API.
Task Status Polling
Both modes utilize normalizeApimartTask() to convert APIMart's response format into a unified shape: { taskId, status, progress, image, expiresAt, cost, ... }.
- Platform polling uses
fetchPlatformTask(taskId, accessToken, language), which queries/api/generation/statusand internally forwards togetApimartTask(). - Personal polling uses
fetchPersonalTask(taskId, apiKey, language)to callGET https://api.apimart.ai/v1/tasks/<taskId>directly.
The pollApimartTask(fetchTask, options) utility manages the polling lifecycle, repeatedly invoking the fetch function until isTerminalApimartStatus(status) returns true (indicating completed or failed status). It respects Retry-After headers when encountering APIMART_RATE_LIMITED errors and supports cancellation via AbortSignal.
Error Handling and Rate Limiting
The implementation provides granular error translation through the apimartErrorCode() helper, which maps HTTP status codes to specific semantic identifiers:
APIMART_API_KEY_INVALIDfor authentication failuresAPIMART_BALANCE_REQUIREDfor insufficient creditsAPIMART_RATE_LIMITEDfor throttling scenarios
Server-side errors are wrapped with upstreamError(), while client-side errors use responseError(). The publicErrorCode() function further maps these internal codes to public-facing messages suitable for API consumers, translating to appropriate HTTP status codes such as 503 for upstream busy states or 500 for internal failures.
Practical Implementation Examples
Submitting a Generation via Platform API
// POST /api/generate-image
await fetch('/api/generate-image', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
caseId: 123,
prompt: 'A cyberpunk city at sunrise',
language: 'en'
})
});
The server handler in api/generate-image.js processes this request and internally calls submitApimartGeneration() (defined at line 44 in api/_lib/apimart.js) to communicate with APIMart.
Direct Generation with Personal API Key
import { submitPersonalGeneration, getStoredApimartKey } from './apimartClient.js';
const apiKey = getStoredApimartKey(); // reads from localStorage
const result = await submitPersonalGeneration(
'A futuristic robot painting',
apiKey,
'en'
);
// result => { taskId: 'task_abc123…', status: 'submitted' }
Polling for Task Completion
import { pollApimartTask, fetchPersonalTask } from './apimartClient.js';
const apiKey = getStoredApimartKey();
const taskId = 'task_…';
await pollApimartTask(
() => fetchPersonalTask(taskId, apiKey, 'en'),
{
onProgress: t => console.log('Progress', t.progress),
maxAttempts: 100,
intervalMs: 2000
}
);
// Returns normalized task object when status becomes 'completed' or 'failed'
Retrieving Cached Results
import { getSavedGeneration } from './apimartClient.js';
const saved = getSavedGeneration(123); // caseId = 123
if (saved) {
console.log('Cached image URL:', saved.image);
}
Server-Side Error Translation
import { publicErrorCode, publicErrorStatus } from './api/generate-image.js';
try {
// ... generation logic
} catch (err) {
const code = publicErrorCode(err);
const status = publicErrorStatus(code);
res.status(status).json({ ok: false, error: code });
}
Summary
- APIMart integration in awesome-gpt-image-2 uses a three-tier architecture separating shared utilities (
shared/apimart.js), server handlers (api/_lib/apimart.js,api/generate-image.js), and browser clients (src/apimartClient.js). - Dual operation modes support both platform-mediated requests (using server-stored API keys) and personal key workflows (direct browser-to-APIMart communication).
- Task lifecycle management includes submission via
submitApimartGeneration()orsubmitPersonalGeneration(), polling throughpollApimartTask(), and normalization vianormalizeApimartTask(). - Robust error handling maps upstream APIMart errors to semantic codes like
APIMART_RATE_LIMITEDandAPIMART_API_KEY_INVALID, with appropriate HTTP status code translation for API consumers. - Local persistence stores API keys and generation history in
localStorageusing version-prefixed keys to maintain state across sessions.
Frequently Asked Questions
What environment variables are required to configure APIMart in awesome-gpt-image-2?
The server-side integration requires APIMART_API_KEY to be set in the environment. The getApimartConfig() function in api/_lib/apimart.js checks for this variable to determine if the provider is properly configured before attempting any upstream requests.
How does the system handle APIMart rate limits?
When APIMart returns rate limit errors, the client detects APIMART_RATE_LIMITED codes and respects the Retry-After header. The pollApimartTask() utility automatically implements backoff strategies, while the server translates these into 503 status codes with appropriate retry guidance for API consumers.
Can users use their own APIMart API keys instead of the platform's?
Yes. The src/apimartClient.js module supports a personal key mode through submitPersonalGeneration() and fetchPersonalTask(), allowing users to store their API key in localStorage (under gpt-image-2-apimart-key:v1) and make direct requests to https://api.apimart.ai/v1/images/generations without routing through the platform's server infrastructure.
Where are generation tasks stored during processing?
Platform-generated tasks are persisted in Supabase within the generation_reservations table, allowing the system to track usage and task states across distributed workers. Client-side tasks and results are cached in localStorage using keys gpt-image-2-pending-tests:v1 and gpt-image-2-generated-tests:v1 for immediate retrieval without repeated API calls.
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 →