> ## Documentation Index
> Fetch the complete documentation index at: https://docs.makelocalads.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Render listing images

> Render saved listing ideas in a batch, or render one slot at a time.

[← Listing images](/listing-images/overview)

**Endpoints:**
`POST https://makelocalads.com/api/v1/amazon-listing-images` and
`POST https://makelocalads.com/api/v1/amazon-listing-ideas/{idea_id}/image`
**Permission:** `amazon_listings:generate`

Render the saved ideas for a marketplace, in a batch or one slot at a time.
Each rendered image costs 2 credits.

## Usage notes

* Batch render: `idea_ids` renders the listed slots, or every saved idea when
  omitted; `max_creatives` renders only the first N, main image first, which
  is how the workspace fits a batch to the credit balance.
* One slot: `POST /amazon-listing-ideas/{idea_id}/image` renders or re-renders
  one slot, and can change its direction first, like the workspace's "Edit
  direction and regenerate".
* A slot keeps only its newest image in `image_url`. Earlier images stay in
  `GET /creatives?type=amazon_listing`.
* `max_credits` refuses a batch with `422` before anything is charged if it
  would cost more.

## Quick start

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request POST \
    --url https://makelocalads.com/api/v1/amazon-listing-images \
    --header "Authorization: Bearer $LOCALADS_API_KEY" \
    --header "Content-Type: application/json" \
    --header "Idempotency-Key: listing-us-3310" \
    --data '{
      "product_id": "a1516a75-9be5-461a-93af-c1896a0a3127",
      "marketplace": "us",
      "max_creatives": 5,
      "max_credits": 10
    }'
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const response = await fetch(
    "https://makelocalads.com/api/v1/amazon-listing-images",
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.LOCALADS_API_KEY}`,
        "Content-Type": "application/json",
        "Idempotency-Key": "listing-us-3310",
      },
      body: JSON.stringify({
        product_id: "a1516a75-9be5-461a-93af-c1896a0a3127",
        marketplace: "us",
        max_creatives: 5,
        max_credits: 10,
      }),
    },
  );

  const batch = await response.json();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import os
  import requests

  response = requests.post(
      "https://makelocalads.com/api/v1/amazon-listing-images",
      headers={
          "Authorization": f"Bearer {os.environ['LOCALADS_API_KEY']}",
          "Content-Type": "application/json",
          "Idempotency-Key": "listing-us-3310",
      },
      json={
          "product_id": "a1516a75-9be5-461a-93af-c1896a0a3127",
          "marketplace": "us",
          "max_creatives": 5,
          "max_credits": 10,
      },
  )

  batch = response.json()
  ```
</CodeGroup>

## Input fields

<ParamField body="product_id" type="string" required>
  The product the listing images are for.
</ParamField>

<ParamField body="marketplace" type="string" required>
  An `id` from [Marketplaces](/listing-images/marketplaces).
</ParamField>

<ParamField body="idea_ids" type="array">
  The slots to render, 1 to 9 unique idea ids from
  `GET /amazon-listing-ideas`. Omit to render every saved idea.
</ParamField>

<ParamField body="max_creatives" type="integer">
  Render only the first N saved ideas, main image first, 1 to 9. Omit to
  render all of them.
</ParamField>

<ParamField body="max_credits" type="integer">
  Refuse the request with `422 credit_limit_exceeded`, before anything is
  charged, if it would cost more than this many credits.
</ParamField>

<Accordion title="Complete JSON schema">
  ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "type": "object",
    "additionalProperties": false,
    "required": ["product_id", "marketplace"],
    "properties": {
      "product_id": { "type": "string", "format": "uuid" },
      "marketplace": { "type": "string" },
      "idea_ids": {
        "type": "array",
        "minItems": 1,
        "maxItems": 9,
        "uniqueItems": true,
        "items": { "type": "string", "format": "uuid" }
      },
      "max_creatives": { "type": "integer", "minimum": 1, "maximum": 9 },
      "max_credits": { "type": "integer", "minimum": 1 }
    }
  }
  ```
</Accordion>

## Response

`202 Accepted`, with a `Location` header and the batch: the slots it started
and `credits_charged`:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "9a7c3f5e-8d2b-4e6a-b1c4-0e5f7a9c2b6d",
  "product_id": "a1516a75-9be5-461a-93af-c1896a0a3127",
  "marketplace": "us",
  "credits_charged": 10,
  "images": [
    {
      "id": "4d6f8a1c-3e5b-4c7d-9f1a-2b4c6d8e0f1a",
      "product_id": "a1516a75-9be5-461a-93af-c1896a0a3127",
      "marketplace": "us",
      "position": 0,
      "slot_type": "main",
      "title": "MAIN IMG",
      "summary": "The throw folded on pure white, full product in frame, soft shadow.",
      "creative_id": "8c2e6a9f-1b4d-4f7a-a3c5-2d8e0f1a4b6c",
      "status": "in_progress",
      "image_url": null,
      "updated_at": "2026-09-25T10:10:00.000Z"
    }
  ]
}
```

Poll `GET /amazon-listing-ideas?product_id=...&marketplace=us` with backoff
until each slot's `status` is `completed` or `failed`. See
[Polling](/concepts/polling).

## Render one slot

To render or re-render a single slot, optionally with a new direction:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST \
  --url https://makelocalads.com/api/v1/amazon-listing-ideas/4d6f8a1c-3e5b-4c7d-9f1a-2b4c6d8e0f1a/image \
  --header "Authorization: Bearer $LOCALADS_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "summary": "Same shot, but on a linen-covered sofa." }'
```

The response is `202 Accepted` with the idea, whose `status` is now `queued`.
Both fields are optional: `summary` (1 to 2,000 characters) changes the
direction before rendering, and `max_credits` caps the cost. The request body
can be empty.

## Errors

| Status | Code | Meaning |
| - | - | - |
| `400` | `invalid_request` | An unknown marketplace or field |
| `404` | `product_not_found`, `idea_not_found` | Not available to you |
| `422` | `request_rejected` | No saved idea has a direction to render |
| `422` | `insufficient_credits` | Not enough credits. Nothing was charged |
| `422` | `credit_limit_exceeded` | The batch would cost more than `max_credits` |

See [Errors and retries](/concepts/errors) for the error format.
