# How to Batch Generate Images Using Structured Prompt Protocols with Awesome GPT Image 2

> Batch generate images using structured prompt protocols with apimartClient.js. Submit parallel tasks, poll for completion, and retrieve results for efficient image creation.

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

---

**Batch generate images using structured prompt protocols by leveraging the [`apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/apimartClient.js) client to submit parallel generation tasks, poll for completion, and retrieve results from the APIMart service.**

The **awesome-gpt-image-2** repository provides a production-ready JavaScript client for orchestrating large-scale image generation workflows. By utilizing **structured prompt protocols**—detailed, reusable prompt templates stored in [`src/image25/realCases.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/image25/realCases.js)—you can batch generate images with consistent layout, composition, and visual language across hundreds of tasks. The architecture separates prompt definition from execution logic, enabling you to queue multiple generations simultaneously while monitoring their progress through a unified polling mechanism.

## Core Workflow for Batch Image Generation

The batch generation process follows a four-phase pipeline implemented across the client's utility modules. Each phase handles a specific concern: payload construction, request submission, status monitoring, and result normalization.

### Building the Payload

Before submitting any request, prompts must be sanitized and wrapped with metadata. The `buildApimartGenerationPayload()` function in [`shared/apimart.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/shared/apimart.js) (line 7) handles this transformation, adding the specified language code, optional webhook URL, and cleaning the prompt string for transmission.

```javascript
import { buildApimartGenerationPayload } from './shared/apimart.js';

const payload = buildApimartGenerationPayload(
  "Create a premium beverage campaign poster...",
  'en',
  'https://your-webhook.com/notify'
);

```

### Submitting Generation Requests

The `submitPersonalGeneration()` method in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js) (line 103) initiates the generation by sending a `POST` request to `/v1/images/generations`. It returns a `taskId` that serves as the unique identifier for tracking the job.

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

const { taskId } = await submitPersonalGeneration(prompt, apiKey, language);

```

### Polling Task Status

Once submitted, tasks require polling until they reach a terminal state. The `fetchPersonalTask()` function (line 125 in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js)) retrieves the current status, while `isTerminalApimartStatus` (from [`shared/apimart.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/shared/apimart.js)) determines if the task has completed successfully or failed.

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

const task = await fetchPersonalTask(taskId, apiKey, language);
if (task.status === 'succeeded') {
  return task.output; // Contains image URL(s)
}

```

### Retrieving Final Results

Completed tasks are normalized using `normalizeApimartTask()` (found in [`api/_lib/apimart.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/apimart.js), line 52). This function standardizes the response format, extracting image URLs and error information into a consistent structure regardless of the raw API response format.

## Structured Prompt Architecture

The repository distinguishes between free-form prompts and **structured prompt protocols**—detailed specifications that encode layout directives, subject consistency rules, and branding constraints. These protocols are stored in [`src/image25/realCases.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/image25/realCases.js) and designed for batch reuse.

### Composition and Layout Directives

Unlike simple text descriptions, structured prompts define technical parameters such as grid size, panel count, and character consistency requirements. An example entry specifies:

```javascript
{
  "prompt": "Create a Cannes-level premium summer beverage campaign poster...",
  "en": "Six-panel structure, character consistency, LIMORA text and prompt adherence"
}

```

These self-contained recipes ensure that when you batch generate images, each output adheres to the same visual grammar, making them suitable for multi-panel advertisements or themed galleries.

### Importing the Prompt Library

To use the built-in structured prompts, import the `realCases` array and pass subsets to your batch processor:

```javascript
import { realCases } from './src/image25/realCases.js';

// Filter for specific campaign types
const beveragePrompts = realCases.filter(p => p.en.includes('beverage'));
await batchGenerate(beveragePrompts);

```

## Implementing the Batch Generation Pattern

Combine the core workflow functions with Promise-based concurrency to process multiple structured prompts efficiently. The following pattern demonstrates how to manage parallel submissions while respecting API constraints.

```javascript
import { submitPersonalGeneration, fetchPersonalTask } from '../src/apimartClient.js';
import { realCases } from '../src/image25/realCases.js';

const API_KEY = 'YOUR_APIMART_KEY';
const LANGUAGE = 'en';
const MAX_CONCURRENT = 5; // Adjust based on rate limits

async function batchGenerate(prompts) {
  // Phase 1: Submit all generation requests in parallel
  const pendingTasks = prompts.map(p => 
    submitPersonalGeneration(p.prompt, API_KEY, LANGUAGE)
  );
  const submittedTasks = await Promise.all(pendingTasks);
  
  // Phase 2: Poll each task until completion
  const results = await Promise.all(
    submittedTasks.map(async ({ taskId }) => {
      // Validate task ID before polling
      while (true) {
        const task = await fetchPersonalTask(taskId, API_KEY, LANGUAGE);
        
        if (task.status === 'succeeded') {
          return task.output; // Array of image URLs
        }
        if (task.status === 'failed') {
          throw new Error(`Task ${taskId} failed: ${task.error}`);
        }
        
        // Wait 2 seconds before next poll
        await new Promise(resolve => setTimeout(resolve, 2000));
      }
    })
  );
  
  return results;
}

// Execute batch on structured prompt library
batchGenerate(realCases)
  .then(images => console.log('Generated images:', images))
  .catch(err => console.error('Batch failed:', err));

```

This implementation uses `Promise.all` to launch **parallel requests**, significantly reducing total processing time compared to sequential generation.

## Handling Rate Limits and Validation

Production batch workflows must gracefully handle API rate limiting and input validation. The client provides specific utilities for these concerns.

### Rate Limit Back-off

When the API returns a `429` status or similar error, the `responseError` helper (line 81 in [`apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/apimartClient.js)) attaches a `retryAfterMs` field indicating the required wait time. Implement exponential back-off using this value:

```javascript
try {
  await submitPersonalGeneration(prompt, apiKey, language);
} catch (error) {
  if (error.retryAfterMs) {
    await new Promise(resolve => setTimeout(resolve, error.retryAfterMs));
    // Retry logic here
  }
}

```

### Task ID Validation

Before entering polling loops, validate task IDs using `isValidApimartTaskId()` from [`shared/apimart.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/shared/apimart.js) (line 8). This prevents unnecessary API calls with malformed identifiers:

```javascript
import { isValidApimartTaskId } from './shared/apimart.js';

if (!isValidApimartTaskId(taskId)) {
  throw new Error(`Invalid task ID format: ${taskId}`);
}

```

## Summary

- **Batch generate images** by mapping structured prompts to `submitPersonalGeneration()` calls and awaiting the results with `Promise.all`.
- Use **`buildApimartGenerationPayload()`** in [`shared/apimart.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/shared/apimart.js) to ensure consistent request formatting across all batch items.
- Monitor task completion through **`fetchPersonalTask()`**, checking for the `succeeded` status to retrieve image URLs.
- Leverage the **[`realCases.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/realCases.js)** library for production-ready structured prompts that include layout and composition directives.
- Implement **`retryAfterMs`** handling to respect rate limits when processing large batches concurrently.
- Validate task IDs with **`isValidApimartTaskId()`** before polling to eliminate invalid network requests.

## Frequently Asked Questions

### What defines a structured prompt protocol?

A structured prompt protocol is a detailed, reusable text template that encodes specific visual constraints such as panel layouts, character consistency rules, and branding requirements. According to the awesome-gpt-image-2 source code, these protocols are stored in [`src/image25/realCases.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/image25/realCases.js) and include both the generation prompt and metadata describing structural requirements like "Six-panel structure" or "Cannes-level premium" styling.

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

The client implements automatic error handling through the `responseError` helper in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js) (line 81), which extracts `retryAfterMs` values from API responses. When a `429` status occurs, your batch processor should catch this error and wait the specified duration before retrying, preventing account throttling while maintaining throughput.

### Can I mix custom prompts with the built-in real cases library?

Yes. The `batchGenerate()` function accepts any array of objects containing a `prompt` property. You can combine entries from [`realCases.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/realCases.js) with custom objects, filter the library by category using string matching on the `en` field, or pass entirely user-defined prompts while maintaining the same execution workflow.

### What is the maximum recommended concurrency for batch operations?

While the repository does not enforce a hard limit, the example implementation sets `MAX_CONCURRENT = 5` as a conservative default. You should adjust this value based on your APIMart subscription tier's rate limits. Monitor for `429` responses and implement the `retryAfterMs` back-off strategy to dynamically adapt to current API capacity.