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

# Reference images

> Upload original photos, attach multiple views, and choose reference intent.

Available with **Personal and Team keys**. Upload and generate within the same account.

## Upload local files and supply multiple views

Upload local files as `multipart/form-data`; you do not need to host images yourself.
Use the repeated field name `files`. Let your HTTP client set the multipart boundary
(do not manually set a JSON Content-Type for this request).

```bash theme={null}
curl --fail-with-body "https://api.gizmo.antimlabs.com/v1/images" \
  -H "Authorization: Bearer $GIZMO_API_KEY" \
  -F "files=@./front.jpg" \
  -F "files=@./back.png"
```

The `201 Created` response contains `images` in upload order. Each item has `id`,
`content_type`, `size_bytes`, `width`, `height`, and `sha256`. Save the returned IDs:

```json theme={null}
{
  "prompt": "Recreate this object with working moving parts",
  "reference_images": [
    {"image_id": "IMAGE_ID_FROM_UPLOAD_1", "view": "front"},
    {"image_id": "IMAGE_ID_FROM_UPLOAD_2", "view": "back"},
    {"url": "https://example.com/object-top.jpg", "view": "top"}
  ]
}
```

Send that JSON to `POST /v1/assets`. Replace the placeholder IDs with real upload IDs.
Each reference has **exactly one** of `image_id` or `url`. Accepted view labels are
`front`, `back`, `left`, `right`, `top`, `bottom`, `perspective`, and `detail`.
Labels are optional user descriptions, not calibrated camera poses. You can supply
several details or perspectives. With both reference fields present, legacy
`reference_image_urls` come first, followed by `reference_images` in order.

Limits: **8 files per upload; 8 references per generation; 20 MiB and 40 million
pixels per file; 80 MiB of file content per upload batch**. Supported formats are
non-animated PNG, JPEG, and WebP. Invalid files are rejected before the batch is
stored. Original bytes are retained without a mandatory crop or concept redraw;
model-specific resized copies can be derived separately. Uploads with identical
bytes reuse the same ID within your account. Image IDs are private and cannot be
used by another account. Uploads currently remain stored without automatic expiry.

`GET /v1/images/{id}` reads metadata. `GET /v1/images/{id}/content` downloads the exact
original bytes. Queued jobs resolve fresh access URLs when they run, so an upload
ID does not expire while a job is waiting. External URLs must remain accessible
when the worker runs; use uploads if you need a durable reference.

Multiple supplied images use the Blender authoring path because the static mesh
backend accepts only a single image. All original views and labels are retained.
`reference_intent.requested_views` is a separate advanced option for **generated
hypotheses**; it is not how you attach observed views and is empty by default.

## Reference fidelity

Uploaded product photos are preserved for reconstruction by default. For an object
inside a scene, the planner keeps the selected original photos and binds them to
that object's name. It does not generate a replacement product shot first.

The optional `reference_intent` request field selects `reconstruct`, `extract`,
`modify`, or `design`. Use `modify` for requested changes to the pictured object,
or `design` when asking for a new design inspired by the inputs. Your prompt
remains the user instruction. Additional generated views are optional hypotheses,
not measurements of unseen surfaces.

### Python: local files and URL references

```python theme={null}
import os
import uuid
import httpx

with httpx.Client(
    base_url="https://api.gizmo.antimlabs.com/v1/",
    headers={"Authorization": f"Bearer {os.environ['GIZMO_API_KEY']}"},
    timeout=120,
) as client:
    with open("front.jpg", "rb") as front, open("back.png", "rb") as back:
        upload = client.post("images", files=[
            ("files", ("front.jpg", front, "image/jpeg")),
            ("files", ("back.png", back, "image/png")),
        ])
    upload.raise_for_status()
    images = upload.json()["images"]
    # Save the key before sending; reuse it if this POST needs to be retried.
    key = str(uuid.uuid4())
    response = client.post("assets", headers={"Idempotency-Key": key}, json={
        "prompt": "Recreate this object with working joints",
        "reference_images": [
            {"image_id": images[0]["id"], "view": "front"},
            {"image_id": images[1]["id"], "view": "back"},
            {"url": "https://example.com/object-top.jpg", "view": "top"},
        ],
    })
    response.raise_for_status()
    print(response.json()["job_id"])
```

For URL-only generation, omit the upload and use `reference_image_urls` or
`reference_images: [{"url": "https://your-host/your-image.jpg", "view": "front"}]`.
Replace all example URLs with accessible images. API keys belong on your server, not in browser bundles.

Reference URLs must serve image bytes directly. Redirect responses are not followed; use the final image URL or upload the local file with `POST /v1/images`.

[Upload reference images](/api-reference/images/upload-reference-images) · [Generate one asset](/api-generate) · [Generate a batch](/api-batches)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.