TL;DR
recraft/creative-upscaleenlarges an image and redraws its texture and detail. The request body is one field,image_url. There is no prompt and no scale setting.- It runs on the unified
/v1/tasksflow:POSTto get ataskId, pollGET /v1/tasks/<taskId>, download fromdata.output[0].url. - In our run a 1254×1254 PNG came back as a 4096×4096 WebP of about 19.8 MB after roughly 60 seconds. Budget for the wait and the file size.
What you need
A hiapi API key from the dashboard, and a publicly reachable image URL. The model page lists the input limits: PNG recommended, up to 20 MB, each side 256–4096 px, up to 16 MP.
If you need text, logos or product detail to stay exactly as they are, use Recraft Crisp Upscale instead. Creative Upscale redraws, so small elements can change.
Minimal curl request
export HIAPI_KEY=sk-your-key
curl -s https://www.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "recraft/creative-upscale",
"input": { "image_url": "https://example.com/old-illustration.png" }
}'
The response is a task handle:
{"code":200,"data":{"taskId":"tk-hiapi-01M5K8J899THH6XJK99TAZ4VSD"},"message":"success"}
Poll it until data.status is success:
curl -s https://www.hiapi.ai/v1/tasks/tk-hiapi-01M5K8J899THH6XJK99TAZ4VSD \
-H "Authorization: Bearer $HIAPI_KEY"
Python: submit, poll, save
import os, time, requests
BASE = "https://www.hiapi.ai"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_KEY']}"}
def upscale(image_url: str, out_path: str) -> str:
r = requests.post(f"{BASE}/v1/tasks", headers=HEADERS, timeout=30, json={
"model": "recraft/creative-upscale",
"input": {"image_url": image_url},
})
r.raise_for_status()
task_id = r.json()["data"]["taskId"]
deadline = time.time() + 300
while time.time() < deadline:
time.sleep(5)
try:
d = requests.get(f"{BASE}/v1/tasks/{task_id}", headers=HEADERS, timeout=30).json()["data"]
except requests.RequestException:
continue # transient network error: keep polling the SAME taskId
if d["status"] == "success":
url = d["output"][0]["url"]
with open(out_path, "wb") as f:
f.write(requests.get(url, timeout=120).content)
return task_id
if d["status"] in ("fail", "failed"):
raise RuntimeError(f"task {task_id} failed: {d}")
raise TimeoutError(f"task {task_id} still running; re-poll it, do not resubmit")
upscale("https://example.com/old-illustration.png", "upscaled.webp")
Two details matter in production. First, never resubmit on a timeout: every submit creates a new billable task, so keep the taskId and re-poll it. Second, save the file immediately; output URLs carry an expireAt and the host is a temporary one.
Production notes
- Use a callback for batches. Instead of polling you can pass
callback: {"url": "...", "when": "final"}in the task body and let hiapi call you when the task ends. Treat thetaskIdas the dedupe key. - Polling interval of 5 s is enough. One task took about a minute, so polling faster only adds requests.
- Validate the URL before you submit. The platform rejects malformed URLs up front (see below), but an unreachable
https://URL is a different failure and is better caught on your side with a quickHEADrequest.
What we saw in a real run
We ran one real request with the example input image from the model page (a 1254×1254 PNG of a mountain cabin).
| Item | Observed |
|---|---|
| Submit response | {"code":200,"data":{"taskId":"tk-hiapi-01M5K8J899THH6XJK99TAZ4VSD"}} |
| Status sequence | handling → archiving → success |
Time from created to completed | 61 seconds (1792721625 → 1792721686) |
| Output | one image, WebP, https://temp.hiapi.ai/.../...-0.webp with an expireAt about 7 days out |
| Input size | 1254×1254 PNG, 2.7 MB |
| Output size | 4096×4096 WebP, about 19.8 MB |
Things worth knowing from that run:
archivinghas nooutputyet. The task reportscompletedandstatus: "archiving"for a few polls while the result is moved to storage. Onlystatus == "success"carriesoutput[0].url, so do not read the URL when you first see acompletedtimestamp.- The result is not a clean 2×. The 1254 px input became 4096 px, about 3.3× per side. The model page shows the same pair and exposes no scale field, so plan for the output being decided by the model, not by you. If you need exactly 2×, Crisp Upscale is the endpoint with that contract.
- Output files are large. 19.8 MB for one image is more than the 20 MB input limit would let you feed straight back in, so do not chain a second pass on the output without resizing.
- Detail is redrawn, not just sharpened. The model page's own note on this pair says composition, light and colors are largely kept while logs, stonework and railing are redrawn, and some small elements, such as a tree by the porch, change. Review output before replacing a brand asset.
- A bad URL fails fast. Sending
"image_url": "not-a-url"returned HTTP 400 immediately:{"code":400,"data":null,"error_code":"INVALID_REQUEST","message":"invalid input: image_url: 'not-a-url' does not match pattern '^https?://'"}. The pattern is the only check we exercised; we did not test the 256 px minimum or the 16 MP ceiling.
We ran one task, so the 61 s figure is a single sample, not a benchmark.
Creative Upscale or Crisp Upscale?
Both take a single image_url and no prompt. They differ in what they do to the pixels and in price.
| Creative Upscale | Crisp Upscale | |
|---|---|---|
| Model id | recraft/creative-upscale | recraft/crisp-upscale |
| Behavior | Enlarges and redraws texture and detail | Doubles width and height, keeps content and lettering |
| Best for | Old illustrations, small or low-res art | Product photos, posters with text, design assets |
| Price | Much higher per image; see pricing | See the Crisp pricing article |
The per-image price of Creative Upscale is far above Crisp's (compare the live numbers on the pricing page), so use it only when you actually want detail regenerated. For general resolution workflows across models, see Increase image resolution with hiapi.
Related
- Recraft Creative Upscale model page
- Recraft Crisp Upscale API guide
- Recraft Remove Background API guide: upscale first, then cut out the subject
- Increase image resolution with the hiapi API
- hiapi pricing
FAQ
Do I need a prompt? No. The model page describes a single image input with no prompt or other settings, and our request used only image_url.
Can I choose the output size? Not through the API. There is no scale field; our 1254 px input came back at 4096 px.
Will text and logos survive? Not guaranteed. Detail is regenerated and small elements can change, so use Crisp Upscale for lettered assets.
What output format do I get? A WebP in our run, delivered from a temporary URL that expires, so download it right away.
How long does it take? About a minute for our single run; build your client for waits of that order.





