# How to Use freestylefly/awesome-gpt-image-2 for Batch Image Generation

> Master batch image generation with freestylefly/awesome-gpt-image-2. Learn to submit async requests, poll task IDs, and collect image URLs for efficient bulk creation.

- Repository: [苍何/awesome-gpt-image-2](https://github.com/freestylefly/awesome-gpt-image-2)
- Tags: how-to-guide
- Published: 2026-09-08

---

**freestylefly/awesome-gpt-image-2 enables batch image generation by submitting multiple asynchronous requests to the APIMart API, polling each taskId until completion, and collecting the resulting image URLs.**

The open-source **freestylefly/awesome-gpt-image-2** repository provides a complete Vercel-based pipeline for generating images at scale. It leverages the APIMart asynchronous API to process hundreds of generation jobs without blocking your application, making it ideal for batch workflows that require high-throughput image creation.

## Architecture Overview for Batch Processing

The repository implements a full-stack pipeline where batch operations rely on three core components working together asynchronously:

- **[`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js)** – The server-side endpoint that receives generation requests, reserves credits in Supabase, and forwards jobs to APIMart
- **[`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js)** – Client-side utilities including `submitPlatformGeneration` and `pollApimartTask` for managing task lifecycles
- **[`api/generation/status.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generation/status.js)** – The status endpoint that queries APIMart for real-time task updates

According to the source code in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js), each submission creates a reservation record in the `generation_reservations` table and returns a unique `taskId`. The system never blocks while waiting for image generation; instead, you poll the `taskId` later to retrieve results when APIMart finishes processing.

## Submitting Multiple Generation Requests

### Preparing Your Job List

A batch workflow starts with an array of case IDs and prompts. Each object in your array represents one image generation job that the system will track independently.

```javascript
const jobs = [
  { caseId: 1, prompt: 'A futuristic city skyline at sunset, photorealistic' },
  { caseId: 166, prompt: 'Twelve Gold Saints playing cards, stylized illustration' },
  { caseId: 310, prompt: 'Snack brand technical breakdown, clean infographic' }
];

```

### Parallel Submission with submitPlatformGeneration

The `submitPlatformGeneration` function in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js) handles the HTTP POST to `/api/generate-image`. For batch processing, map your jobs array to parallel promises to maximize throughput:

```javascript
import { submitPlatformGeneration } from './src/apimartClient.js';

async function submitBatch(jobs, accessToken) {
  const submitPromises = jobs.map(job =>
    submitPlatformGeneration({
      caseId: job.caseId,
      prompt: job.prompt,
      language: 'en',
      accessToken
    })
  );

  const submissions = await Promise.all(submitPromises);
  console.log('Submitted tasks:', submissions.map(s => s.taskId));
  return submissions; // Array of { taskId, status } objects
}

```

The function returns immediately with a `taskId` for each job, allowing you to fire dozens or hundreds of requests without waiting for image generation to complete.

## Polling and Retrieving Results

### Using pollApimartTask for Status Monitoring

Once you have your `taskId`s, use the `pollApimartTask` helper (implemented at lines 15-52 in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js)) to monitor each job until it reaches a terminal state (`completed` or `failed`). This helper automatically handles rate-limit retries when APIMart returns `APIMART_RATE_LIMITED` status.

```javascript
import { pollApimartTask, fetchPlatformTask } from './src/apimartClient.js';

async function pollAllTasks(submissions, accessToken) {
  const results = await Promise.all(
    submissions.map(async ({ taskId }) => {
      const fetchTask = () => fetchPlatformTask(taskId, accessToken, 'en');
      const finalTask = await pollApimartTask(fetchTask);
      return { taskId, status: finalTask.status, result: finalTask };
    })
  );
  return results;
}

```

### Extracting Image URLs from Completed Tasks

After polling completes, filter for successful generations and extract the image URLs from the `output` array. According to the APIMart specification referenced in the source code, completed tasks store the image URL at `result.output[0].url`.

```javascript
const results = await pollAllTasks(submissions, accessToken);
const completed = results.filter(r => r.status === 'completed');

console.log('Generated images:', completed.map(c => c.result.output[0].url));

```

## Optional Local Storage Helpers

The repository includes browser storage utilities to persist pending tasks and generated images between sessions. These helpers use `APIMART_PENDING_STORAGE_KEY` and `GENERATED_TESTS_STORAGE_KEY` to manage localStorage entries.

```javascript
import { 
  savePendingGeneration, 
  getPendingGeneration,
  clearPendingGeneration 
} from './src/apimartClient.js';

// Cache a pending task immediately after submission
savePendingGeneration(caseId, { taskId, status: 'submitted' }, localStorage);

// Retrieve later to avoid duplicate API calls
const pending = getPendingGeneration(caseId, localStorage);

```

These utilities automatically prune expired entries and are defined at lines 54-99 in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js).

## Server-Side Batch Implementation

For automated batch processing (such as Vercel cron jobs), you can run the same workflow inside a serverless function. The following example uses the Supabase client from [`src/supabaseClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/supabaseClient.js) to authenticate requests:

```javascript
import { getSupabaseClient } from './src/supabaseClient.js';
import { submitPlatformGeneration, pollApimartTask, fetchPlatformTask } from './src/apimartClient.js';

export default async function batchHandler(req, res) {
  const supabase = getSupabaseClient();
  const { data: { access_token } } = await supabase.auth.getUser();

  const caseIds = [1, 166, 310];
  const tasks = await Promise.all(
    caseIds.map(id => submitPlatformGeneration({
      caseId: id,
      prompt: `Concept art for case ${id}`,
      language: 'en',
      accessToken: access_token
    }))
  );

  // Sequential polling example for rate-conscious environments
  const results = [];
  for (const { taskId } of tasks) {
    const final = await pollApimartTask(
      () => fetchPlatformTask(taskId, access_token, 'en')
    );
    results.push(final);
  }

  res.json({ completed: results.filter(r => r.status === 'completed') });
}

```

## Summary

- **Submit jobs in parallel** using `submitPlatformGeneration` from [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js) to receive unique `taskId`s for each generation request
- **Poll asynchronously** with `pollApimartTask`, which handles rate limits and retries automatically
- **Retrieve results** from the `output[0].url` property of completed task objects
- **Track credits** via the `generation_reservations` table in Supabase, managed by [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js)
- **Persist state** optionally using the localStorage helpers to cache pending and completed generations

## Frequently Asked Questions

### How does the batch workflow handle API rate limits?

The `pollApimartTask` function in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js) specifically checks for `APIMART_RATE_LIMITED` status responses and implements retry logic with exponential backoff. When APIMart signals rate limiting, the poller waits before retrying the status check, ensuring your batch process continues without manual intervention.

### What is the maximum number of images I can generate in one batch?

The repository itself does not impose a hard limit on batch size; your concurrency is bounded only by your APIMart credit balance and any rate limits imposed by the APIMart platform. Because the architecture is fully asynchronous, you can submit hundreds of jobs simultaneously and poll them independently as resources allow.

### How do I track the status of individual tasks in a batch?

Each submission returns a unique `taskId` that identifies the job in APIMart's system. Use `fetchPlatformTask` (which queries the [`/api/generation/status.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main//api/generation/status.js) endpoint) to check current states, or use `pollApimartTask` to block until a specific task completes. The Supabase `generation_reservations` table also maintains a record linking your case IDs to their respective APIMart task IDs.

### Can I run batch generation from a serverless function?

Yes. The client utilities in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js) work identically in serverless environments like Vercel Functions. Import `submitPlatformGeneration` and `pollApimartTask` directly into your API route handlers, authenticate with a Supabase token via `getSupabaseClient` from [`src/supabaseClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/supabaseClient.js), and execute the same parallel submission and polling logic you would use in a browser.