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 optionalresponse_format=urlalso 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
maskorn > 1;input_fidelityis ignored. - Visual QA: review logos, ingredient text, labels, proportions, and advertising claims before publication.
-
Protocol: the asynchronous
POST /v1/media/generateworkflow 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?
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes โ full credit and traffic to the original publisher.