Image to image
Transform an image you uploaded, guided by a prompt.
Give PierNode an image you have uploaded and an instruction, and get back a new image. The prompt describes the change you want — "make the sky look like dusk", "remove the car on the left", "turn this into a pencil sketch".
This is a general image transformation, not an upscaler: you choose the output size, and it is not derived from the input.
Like every PierNode generation, this is asynchronous: you start a task and poll it until it reaches a terminal state.
Before you start
You need an upload in the READY state. See Uploading an image:
POST /api/v1/uploads → { id, uploadUrl }
PUT <uploadUrl> → your image bytes
POST /api/v1/uploads/{id}/complete → { status: "READY" }Keep that id. It is the assetId below, and it stays valid for as long as the
upload exists, so one upload can feed as many transformations as you like.
POST /api/v1/images/transformations
curl -X POST https://your-piernode-host/api/v1/images/transformations \
-H "Authorization: Bearer $PIERNODE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"assetId": "c8f2a1d4e5b64c9a8f3d2e1b0a9c8d7e",
"prompt": "make the sky look like dusk"
}'Request
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
assetId | string | yes | — | A READY upload of yours. |
prompt | string | yes | — | 1–2000 characters. Describes the change you want. |
quality | string | no | hd | hd (1024 px long edge) or fhd (1280 px long edge). |
aspectRatio | string | no | the input's shape | 1:1, 9:16, 16:9, 4:3, 3:4, 3:2, 2:3. |
By default the output keeps roughly the shape of the image you uploaded, so a
landscape photo stays landscape. Set aspectRatio when you want to change it.
Request bodies are limited to 64 KB. Any field not listed above is ignored — in
particular there is no way to pass an image URL, an object key or a bucket. An
input image is always one of your own uploads, named by assetId.
Response
{
"id": "01JD8Z9K2M4N6P8Q0R2S4T6V8W",
"status": "QUEUED",
"createdAt": "2026-01-01T12:00:00.000Z"
}Poll GET /api/v1/tasks/\{taskId\} until status is SUCCEEDED or FAILED.
Result
{
"id": "01JD8Z9K2M4N6P8Q0R2S4T6V8W",
"status": "SUCCEEDED",
"output": {
"images": [
{
"url": "https://...",
"contentType": "image/png",
"sizeBytes": 1048576
}
]
},
"error": null
}Result links are valid for one hour. Re-poll the task for a fresh one, or copy the file somewhere of your own.
The result is a generation output, not a new upload — it does not get an
assetId, and it does not appear under /v1/uploads. Your input upload is
unchanged and still usable.
Errors
| Status | Meaning |
|---|---|
400 | No usable upload for that assetId — it is not yours, does not exist, or is not READY. |
402 | Your balance is too low to start this generation. |
429 | Too many generation requests. The limit is 60 per minute per account. |
503 | This tier is not currently available. |
Nothing is reserved from your balance unless the task is accepted, and a failed generation is refunded in full.
Pricing
Charged per generated image, one image per request. The fhd tier is priced
separately from hd. Current rates are shown on your dashboard.
Cancelling
POST /api/v1/tasks/\{taskId\}/cancel refunds a task that has not started yet.
Once processing has begun it returns 409, because the work upstream cannot be
recalled.