Dev.to AI ๐Ÿค– Ai ๐Ÿ‘ 0 ๐Ÿ“– 4 min read

Editing Product Photos with Python: Multipart Uploads, Base64 Images, and Safe Retries

Disclosure: I work on API Crest, the API platform used below. I checked the endpoint and parameters against the public API documentation on October 14, 2026. This is a documentation-based walkthrough: I did not execute p

Disclosure: I work on API Crest, the API platform used below. I checked the endpoint and parameters against the public API documentation on October 14, 2026. This is a documentation-based walkthrough: I did not execute paid generation requests, benchmark latency, or verify output quality or prices.

A product-photo editing pipeline starts with an existing image. The tricky engineering parts are uploading files, decoding the response, and not accidentally paying twice when a client times out. This guide demonstrates API Crest's synchronous image-editing route using Python and cURL. It differs from the platform's asynchronous media-generation endpoint.

1. Endpoint and preparation

The API docs document:

  • Base URL: https://api.vv666.ai
  • Image-edit endpoint: POST /v1/images/edits
  • Model ID: gpt-image-2.5 (a provider-documented ID)
  • Auth: Authorization: Bearer API_KEY
  • Multipart image field: repeated image[]
  • Required text fields: model, prompt
  • Default response: data[0].b64_json; an optional response_format=url also exists.

These are documented API Crest values, not universal guarantees of all OpenAI-compatible APIs. Check the live model catalog and account pricing before spending credits.

Install Python requests and place your secret in a local environment variable:

python -m pip install requests
export APICREST_API_KEY="YOUR_API_KEY"

In PowerShell, use $env:APICREST_API_KEY = "YOUR_API_KEY". Never hard-code or publish a live key.

2. Multipart cURL request

If you own or are authorized to process product.png:

curl --request POST "https://api.vv666.ai/v1/images/edits" \
  --header "Authorization: Bearer APICREST_API_KEY" \
  --form "model=gpt-image-2.5" \
  --form "image[][email protected]" \
  --form "prompt=Place this product on a clean wooden desk in morning light. Keep its packaging colors and label as close to the reference as possible." \
  --form "size=1536x1024" \
  --form "quality=high" \
  --form "response_format=b64_json"

cURL builds the multipart boundary automatically; do not set Content-Type: application/json for this upload. A prompt cannot guarantee text, logo or packaging fidelity: manually review generated commercial assets.

3. Python: send one edit and save the image

This script deliberately does not automatically retry a possibly billable POST.

import base64
import os
from pathlib import Path

import requests

source = Path("product.png")
if not source.is_file():
    raise FileNotFoundError(source)

endpoint = "https://api.vv666.ai/v1/images/edits"
headers = {"Authorization": f"Bearer {os.environ['APICREST_API_KEY']}"}

with source.open("rb") as image:
    response = requests.post(
        endpoint,
        headers=headers,
        files={"image[]": (source.name, image, "image/png")},
        data={
            "model": "gpt-image-2.5",
            "prompt": "Place this product on a wooden desk in morning light. Preserve packaging as closely as possible.",
            "size": "1536x1024",
            "quality": "high",
            "response_format": "b64_json",
        },
        timeout=(15, 360),  # illustrative connect/read timeouts; not an SLA
    )

task_id = response.headers.get("X-Task-Id")
if task_id:
    print("Task ID:", task_id)

if not response.ok:
    try:
        error = response.json().get("error", {})
        if isinstance(error, dict) and error.get("task_id"):
            print("Task ID for follow-up:", error["task_id"])
    except (ValueError, AttributeError):
        pass
    response.raise_for_status()

image_b64 = response.json()["data"][0]["b64_json"]
output = Path("edited.png")
output.write_bytes(base64.b64decode(image_b64, validate=True))
print("Saved:", output.resolve())

The endpoint is synchronous; the 360-second example read timeout is a client choice, not a claimed measurement. With the documented response_format=url, handle data[0].url instead; don't assume those URLs last forever.

4. Two reference images

The documented multipart API accepts repeated image inputs:

--form "image[][email protected]" \
--form "image[][email protected]"

To send multiple files in Python requests, pass a list of repeated ("image[]", (filename, stream, mimetype)) entries, not a dictionary with duplicate keys. The docs describe up to 16 references, though individual channels may have lower limits. Validate permissions, file types and sizes.

5. Timeout and billing safety

A client timeout does not prove that the provider canceled processing. Blindly retrying the same POST could create a second billable edit. Don't implement automatic POST retries without a documented idempotency guarantee.

API Crest documents a response X-Task-Id header, possible error.task_id values, and a status/cost lookup:

GET https://api.vv666.ai/v1/skills/task-status?task_id=YOUR_TASK_ID
Authorization: Bearer YOUR_API_KEY

When is_final=true, the docs describe the settled cost as available in the task result. If the connection drops before any headers, you may have no ID: treat the outcome as unknown, reconcile activity/usage, and avoid infinite retries.

Production checklist:

  • Secrets: keep keys server-side, redact logs, and restrict access.
  • Cost: image edits use documented per-image billing; Enhanced channels can cost more. Check live channel/model prices and settled account charges; no invented dollar amounts or savings claims here.
  • Inputs: validate file type, size, image rights, and user authorization.
  • Errors: inspect sanitized status/error objects; IP allowlist restrictions may return 403 / ip_not_allowed.
  • Capabilities: this documented interface does not support mask or n > 1; input_fidelity is ignored.
  • Visual QA: review logos, ingredient text, labels, proportions, and advertising claims before publication.
  • Protocol: the asynchronous POST /v1/media/generate workflow is separate from synchronous /v1/images/edits.

6. What to validate yourself

Before integrating with production, make one authorized low-volume request, check that the response can be decoded, record returned task IDs, and examine actual billing. I have not run that paid test for this article.

Docs: API Crest public API documentation ยท API Crest platform

For developers working with product images, what is hardest: reference fidelity, long-running requests, or avoiding duplicate charges?

๐Ÿ“ฐ Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes โ€” full credit and traffic to the original publisher.