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

# Images & AI-generated artwork

> Attach images to rewards, promotions, raffles, and levels — including images generated by AI

Rewards, promotions, raffles, and levels each support an image shown in the Rigaly app. Every one has a matching image endpoint:

| Resource     | Endpoint                             |
| ------------ | ------------------------------------ |
| Reward       | `POST /api/v1/rewards/{id}/image`    |
| Promotion    | `POST /api/v1/promotions/{id}/image` |
| Raffle       | `POST /api/v1/raffles/{id}/image`    |
| Level (tier) | `POST /api/v1/tiers/{id}/image`      |

All four accept the **same three input styles** — pick whichever your pipeline produces (JPEG, PNG, or WebP, max 5MB):

1. **`multipart/form-data`** with an `image` file field — a normal file upload.
2. **JSON `image_base64`** — raw base64 plus `content_type`, or a `data:` URI. This is what AI image APIs return, so you can generate and attach in one flow.
3. **JSON `image_url`** — a public https URL that Rigaly downloads server-side.

The response returns the hosted `image_url`. `DELETE` on the same path removes it.

## Create a reward with an AI-generated image

The pattern: create the reward, generate the artwork with an image model, then attach it. Because the image endpoint accepts base64 directly, the model's output goes straight to Rigaly — no file handling, no separate hosting.

<CodeGroup>
  ```javascript Node.js theme={null}
  import OpenAI from "openai";
  const openai = new OpenAI();
  const RIGALY = { Authorization: `Bearer ${process.env.RIGALY_API_KEY}` };

  // 1. Create the reward
  const { data: created } = await fetch("https://api.rigaly.com/api/v1/rewards", {
    method: "POST",
    headers: { ...RIGALY, "Content-Type": "application/json" },
    body: JSON.stringify({ name: "Free Cappuccino", points_cost: 1000 }),
  }).then((r) => r.json());
  const rewardId = created.reward.id;

  // 2. Generate artwork (returns base64)
  const img = await openai.images.generate({
    model: "gpt-image-1",
    prompt: "A cozy illustrated cappuccino with latte art, warm colors, flat vector style",
    size: "1024x1024",
  });
  const imageBase64 = img.data[0].b64_json;

  // 3. Attach it — base64 goes straight to Rigaly
  await fetch(`https://api.rigaly.com/api/v1/rewards/${rewardId}/image`, {
    method: "POST",
    headers: { ...RIGALY, "Content-Type": "application/json" },
    body: JSON.stringify({ image_base64: imageBase64, content_type: "image/png" }),
  });
  ```

  ```python Python theme={null}
  import os, requests
  from openai import OpenAI

  openai = OpenAI()
  RIGALY = {"Authorization": f"Bearer {os.environ['RIGALY_API_KEY']}"}

  # 1. Create the reward
  reward = requests.post(
      "https://api.rigaly.com/api/v1/rewards",
      headers=RIGALY,
      json={"name": "Free Cappuccino", "points_cost": 1000},
  ).json()["data"]["reward"]

  # 2. Generate artwork (returns base64)
  img = openai.images.generate(
      model="gpt-image-1",
      prompt="A cozy illustrated cappuccino with latte art, warm colors, flat vector style",
      size="1024x1024",
  )
  image_base64 = img.data[0].b64_json

  # 3. Attach it — base64 goes straight to Rigaly
  requests.post(
      f"https://api.rigaly.com/api/v1/rewards/{reward['id']}/image",
      headers=RIGALY,
      json={"image_base64": image_base64, "content_type": "image/png"},
  )
  ```
</CodeGroup>

<Tip>
  Already have the image hosted somewhere? Skip base64 and pass `{ "image_url": "https://…" }` instead.
</Tip>

## Doing it by chatting with an AI assistant

With the [AI connector](/guides/ai-connector), the assistant has `set_reward_image`, `set_promotion_image`, `set_raffle_image`, and `set_tier_image` tools — each takes an `image_url`.

This works best when the artwork already lives at a public URL. For example: *"Create a 'Free coffee' reward for 1,000 points and set its image to [https://mycdn.com/coffee.png](https://mycdn.com/coffee.png)."* The assistant creates the reward and attaches the image in one go.

<Warning>
  **Images an assistant generates inside the chat usually don't have a public URL**, so it can't hand them to the connector directly — a known limitation of today's AI chat platforms. Until that changes, the reliable paths are: attach from a public `image_url` by chatting, or use the base64 API flow above in a script for fully automated "generate + attach" pipelines.
</Warning>
