Menu
Async API

Pilio API Documentation

Use permanent API keys to create asynchronous image processing, PDF watermark removal, and GPT Image 2 tasks.

On this page

Basics

Pilio API async task flow

Create file -> Upload file -> Create task -> Poll results -> Download file

  1. 1

    Create file

    POST/files/batch-create

    Receive file_id and upload URL

  2. 2

    Upload file

    PUTupload_url

    Send binary to the presigned URL

  3. 3

    Create task

    POST/v1/images/...

    Pass file_id and receive task_id

  4. 4

    Poll results

    GETstatus_url / result_url

    Wait for Succeeded or Failed

  5. 5

    Download file

    GETdownload_url

    Fetch the temporary result URL

Recommended async API flow: prepare a file ID, upload the file, create the task, poll status and result, then download the output file.

All creation endpoints return IDs immediately. After completion, read the file list from result_url and use download_url for the final download.

Authentication

Send your API key with every request. You can use either header form.

Example
Authorization: Bearer pilio_sk_your_key_here
# or
X-API-Key: pilio_sk_your_key_here
Base URL
https://pilio.ai
Content-Type
application/json

5-minute quickstart

This flow creates an upload file, uploads the binary to a presigned URL, creates an async task, then polls for the result.

Example
# 1) Create upload file records. This example explicitly chooses simple upload.
#    Read data.items[0].id and data.items[0].upload_url.
curl -X POST "https://pilio.ai/v1/files/batch-create"   -H "Authorization: Bearer pilio_sk_your_key_here"   -H "Content-Type: application/json"   -d '{"files":[{"nanoid":"V1StGXR8_Z5jdHi6B-myT","name":"reference.png","type":"png","size":1024}],"upload_mode":"simple","storage_intent":"temporary"}'

# 2) Upload the file to the presigned URL. Do not send your Pilio API key here.
#    After a simple upload_url upload succeeds, go to step 3. Do not call /v1/files/:id/complete.
curl -X PUT "<upload_url>"   -H "Content-Type: image/png"   --data-binary @reference.png

# 3) Create an image watermark removal task with the file ID
curl -X POST "https://pilio.ai/v1/images/remove-watermark"   -H "Authorization: Bearer pilio_sk_your_key_here"   -H "Content-Type: application/json"   -d '{"image_file_id":"<file_id>","mode":"auto"}'

# 4) Poll task status until status is Succeeded or Failed
curl -H "Authorization: Bearer pilio_sk_your_key_here"   "https://pilio.ai/v1/tasks/<task_id>/status"

# 5) Fetch the result and download data.files[0].download_url
curl -H "Authorization: Bearer pilio_sk_your_key_here"   "https://pilio.ai/v1/tasks/<task_id>/result"

Response envelope

Every Pilio API response uses the same outer envelope. Check both the HTTP status and code.

Example
{
  "code": 200,
  "message": "success",
  "data": { ... }
}

File upload and download

Image editing and PDF watermark removal endpoints receive file IDs, not raw multipart file bodies. Create upload records first, upload to the returned URL, then pass the file ID to a task endpoint.

  • upload_mode=simple explicitly chooses one-file upload. When upload_url is returned, PUT the file binary to that URL and do not call complete.
  • upload_mode=multipart explicitly chooses multipart upload. When upload_urls is returned, PUT each part in order, collect each ETag, then call complete.
  • upload_mode=auto lets the server choose by file size. Client code should follow the returned field instead of guessing the upload path.
  • Do not send the Pilio API key to presigned upload or download URLs.

Main flow boundaries

  • batch-create only creates file records and upload URLs. It does not upload file content.
  • Returned upload_url: run one PUT, then create the task with items[].id. Do not call /v1/files/:id/complete.
  • Returned upload_urls: after all part PUT requests succeed, call /v1/files/:id/complete, then create the task with items[].id.
  • Task creation accepts file IDs such as image_file_id, image_file_ids, or pdf_file_id. Do not pass nanoid, upload_url, upload_urls, or upload_id.
  • If upload URLs expire or multipart state is lost, call batch-create again to get fresh upload URLs.

POST/v1/files/batch-create

Create file upload records and return either a simple upload_url or multipart upload_urls based on upload_mode and file size.

Request example
Example
{
  "files": [
    {
      "nanoid": "V1StGXR8_Z5jdHi6B-myT",
      "name": "reference.png",
      "type": "png",
      "size": 1024
    }
  ],
  "upload_mode": "simple",
  "storage_intent": "temporary"
}
Request fields
FieldTypeRequiredNotes / allowed values
filesSourceFile[]yesFiles to create upload credentials for; at least one item.
files[].nanoidstringyesClient-generated 21-character nanoid for matching returned file records to local files.
files[].namestringyesOriginal file name, up to 300 characters; extension must match type.
files[].typeenumyesFile extension type, such as jpg, jpeg, png, webp, or pdf.
files[].sizeintegernoFile size in bytes; auto mode uses it to choose upload_url or upload_urls.
upload_modeenumnoauto, simple, or multipart. simple returns upload_url; multipart returns upload_urls; auto lets the server choose by size.
storage_intentenumnoDeveloper API uploads currently only support temporary; use temporary for image editing and PDF watermark removal inputs.
Response data fields
FieldTypeRequiredNotes / allowed values
totalintegeryesNumber of file records created.
itemsFile[]yesFile records; pass the returned id as image_file_id, image_file_ids, or pdf_file_id.
items[].idstringyesFile ID.
items[].nanoidstringyesThe nanoid from your request, useful for client-side matching.
items[].statusFileStatusyesInitially Pending; finish the presigned PUT upload before creating a task with this file ID.
items[].upload_urlstringyes for simple uploadPresigned URL for a single PUT upload. Do not call complete when this field is returned.
items[].upload_urlsUploadPart[]yes for multipart uploadPresigned URLs for multipart PUT uploads. Upload every part, then call complete.
items[].upload_idstringyes for multipart uploadObject storage multipart upload ID, mainly for troubleshooting; complete only needs parts.

POST/v1/files/:id/complete

Complete a multipart upload (optional). Call this only when batch-create returns upload_urls; do not call it for simple upload_url uploads.

Request example
Example
{
  "parts": [
    { "part_number": 1, "etag": ""etag-from-upload-response"" }
  ]
}
Request fields
FieldTypeRequiredNotes / allowed values
idstring(path)yes for multipart uploadFile ID returned as items[].id by batch-create; do not call this endpoint for simple upload_url uploads.
partsCompletedPart[]yes for multipart uploadSuccessfully uploaded parts; part numbers must be continuous and start at 1.
parts[].part_numberintegeryes for multipart uploadPart number, starting at 1.
parts[].etagstringyes for multipart uploadETag response header returned by object storage after each part upload.
Response data fields
FieldTypeRequiredNotes / allowed values
datanull/objectnoSuccess means the multipart object has been merged; simple upload_url uploads do not need this endpoint.

Task polling

Creation endpoints return immediately with a task ID. Poll status_url until the task reaches Succeeded or Failed, then read result files from result_url.

Example
{
  "code": 200,
  "message": "success",
  "data": {
    "task_id": "2048...",
    "status": "Processing",
    "status_url": "/v1/tasks/2048.../status",
    "result_url": "/v1/tasks/2048.../result",
    "created_at": "2026-04-25T12:00:00Z"
  }
}

GET/v1/tasks/:id/status

Query task status. :id is the task_id returned by a creation endpoint.

Request example
Example
No request body.
Request fields
FieldTypeRequiredNotes / allowed values
idstring(path)yesTask ID.
Response data fields
FieldTypeRequiredNotes / allowed values
task_idstringyesTask ID.
statusTaskStatusyesPending, Processing, Succeeded, or Failed.
error_typestringnoFailure category, usually present only when the task failed.
error_messagestringnoFailure message, usually present only when the task failed.
created_atstring(date-time)noTask creation time.
updated_atstring(date-time)noLast update time.
result_urlstringnoURL for reading task results.

GET/v1/tasks/:id/result

Query task results. Successful tasks return downloadable files.

Request example
Example
No request body.
Request fields
FieldTypeRequiredNotes / allowed values
idstring(path)yesTask ID.
Response data fields
FieldTypeRequiredNotes / allowed values
task_idstringyesTask ID.
statusTaskStatusyesIf the task has not succeeded yet, files may be empty.
error_typestringnoFailure category.
error_messagestringnoFailure message.
filesResultFile[]noOne or more output files.
zip_fileResultFilenoMay be present for batched output.

Shared schemas

TaskStatus

FieldTypeRequiredNotes / allowed values
PendingTaskStatusyesCreated and waiting for worker scheduling.
ProcessingTaskStatusyesThe task is running; keep polling status_url.
SucceededTaskStatusyesThe task finished successfully; call result_url for output files.
FailedTaskStatusyesThe task failed; read error_type and error_message.

ResultFile

FieldTypeRequiredNotes / allowed values
idstringyesFile ID.
namestringnoFile name.
typestringnoFile type.
sizeintegernoFile size in bytes.
download_urlstringnoTemporary download URL, issued for successful results.

Errors

Errors keep the same envelope shape. Use the numeric code and structured data for program logic instead of parsing the human message.

Example
{
  "code": 1402,
  "message": "Invalid token",
  "data": null
}

Resources

OpenAPI file

A public OpenAPI JSON file is available for Postman, Apifox, Insomnia, Bruno, code generators, and AI-assisted integration.

Download /developers/pilio-openapi.json

SDK

Pilio now provides an official JavaScript / TypeScript SDK and CLI. For other languages, keep using the OpenAPI JSON as the source of truth and generate a thin client that wraps authentication, response envelopes, polling, and downloads.

Install & usage

Pilio JS SDK / CLIOfficial

pilioai/pilio-js contains the typed @pilio/sdk package and the @pilio/cli command-line tool for Node.js, automation scripts, and CI workflows.

Example
pnpm add @pilio/sdk
pnpm dlx @pilio/cli --help

CLI quick commands

Example
# Run the CLI without global install
pnpm dlx @pilio/cli --help

# Use PILIO_API_KEY from the process environment
pnpm dlx @pilio/cli gpt-image-2 --prompt "A cinematic product photo" --aspect-ratio 3:2
pnpm dlx @pilio/cli nano-banana-2 --prompt "A clean product poster" --aspect-ratio 1:1 --resolution 1K
pnpm dlx @pilio/cli task wait <task_id>

SDK upload and task example

Example
import { readFile } from "node:fs/promises";
import { PilioClient } from "@pilio/sdk";

const client = new PilioClient({
  apiKey: process.env.PILIO_API_KEY!,
});

const image = await readFile("portrait.png");
const file = await client.files.upload({
  name: "portrait.png",
  type: "png",
  data: new Blob([image]),
  size: image.byteLength,
});

const task = await client.images.removeBackground({
  image_file_id: file.id!,
});

const result = await client.tasks.wait(task.task_id);
console.log(result.files);

Agent Skills

Pilio Agent Skills provide small, ready-to-use skill packs for AI agents. They drive Developer API workflows with natural language and delegate execution to @pilio/cli.

Install skills

pilioai/skillsAI

pilioai/skills provides GPT Image 2, Nano Banana 2, background removal, and other skill packs for AI agents to call Pilio Developer API with natural language.

Example
pnpm dlx skills add pilioai/skills --skill gpt-image-2
pnpm dlx skills add pilioai/skills --skill nano-banana-2
pnpm dlx skills add pilioai/skills --skill remove-background

Tool APIs

GPT Image 2

POST/v1/images/gpt-image-2

Create a GPT Image 2 image task. Send only a prompt for text-to-image, or include image_file_ids for reference-image editing or composition.

Request example

Example
{
  "prompt": "A cinematic product photo of an orange perfume bottle",
  "aspect_ratio": "3:2",
  "output_count": 2,
  "resolution": "2K"
}

Request fields

FieldTypeRequiredNotes / allowed values
promptstringyesGeneration or editing prompt, up to 32000 characters.
negative_promptstringnoNegative prompt, up to 32000 characters.
image_file_idsstring[]noReference image file IDs. Omit for text-to-image; pass 1-16 items for reference-image editing or composition. Supports jpg, jpeg, png, and webp.
aspect_ratioenumyes without references; no with references1:1, 3:2, 2:3, 3:4, 4:3, 4:5, 5:4, 16:9, 9:16, 21:9, or auto.
output_countintegernoNumber of output images: 1, 2, or 4.
resolutionenumno1K, 2K, or 4K. Prefer this for normal output-size control.
qualityenumnoAdvanced optional tier: auto, low, medium, or high. Defaults to auto. It affects detail, compute effort, and generation time, not resolution.
preprocess_modeenumnooff or auto.

Response data fields

FieldTypeRequiredNotes / allowed values
task_idstringyesAsync task ID.
statusTaskStatusyesUsually Processing when the task is created.
status_urlstringyesURL for polling task status.
result_urlstringyesURL for reading task results.
created_atstring(date-time)noTask creation time.

Nano Banana 2

POST/v1/images/nano-banana-2

Create a Nano Banana 2 image task. Send only a prompt for text-to-image, or include image_file_ids for reference-image editing or composition.

Request example

Example
{
  "prompt": "Turn these references into a clean product poster",
  "image_file_ids": ["123456789", "123456790"],
  "aspect_ratio": "16:9",
  "resolution": "1K"
}

Request fields

FieldTypeRequiredNotes / allowed values
promptstringyesGeneration or editing prompt, up to 32000 characters.
negative_promptstringnoNegative prompt, up to 32000 characters.
image_file_idsstring[]noReference image file IDs. Omit for text-to-image; pass 1-14 items for reference-image editing or composition. Supports jpg, jpeg, png, and webp.
aspect_ratioenumyes without references; no with references1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9, 1:4, 4:1, 1:8, or 8:1.
output_countintegernoNumber of output images: 1, 2, or 4.
resolutionenumno0.5K, 1K, 2K, or 4K.
preprocess_modeenumnooff or auto.

Response data fields

FieldTypeRequiredNotes / allowed values
task_idstringyesAsync task ID.
statusTaskStatusyesUsually Processing when the task is created.
status_urlstringyesURL for polling task status.
result_urlstringyesURL for reading task results.
created_atstring(date-time)noTask creation time.

Image watermark removal

POST/v1/images/remove-watermark

Create an image watermark removal task with automatic detection or manual boxes.

Request example

Example
{
  "image_file_id": "123456789",
  "mode": "manual",
  "boxes": [{ "x1": 10, "y1": 15, "x2": 60, "y2": 70 }]
}

Request fields

FieldTypeRequiredNotes / allowed values
image_file_idstringyesFile ID of the image to process.
modeenumnoauto detects watermark areas automatically; manual uses explicit boxes. Default: auto.
boxesBox[]yes when mode is manualManual watermark regions, 1-5 boxes. Coordinates are percentages of image width and height.
boxes[].x1integeryes when mode is manualTop-left X, 0-100.
boxes[].y1integeryes when mode is manualTop-left Y, 0-100.
boxes[].x2integeryes when mode is manualBottom-right X, 0-100.
boxes[].y2integeryes when mode is manualBottom-right Y, 0-100.

Response data fields

FieldTypeRequiredNotes / allowed values
task_idstringyesAsync task ID.
statusTaskStatusyesUsually Processing when the task is created.
status_urlstringyesURL for polling task status.
result_urlstringyesURL for reading task results.
created_atstring(date-time)noTask creation time.

Background removal

POST/v1/images/remove-background

Create an image background removal task that returns a transparent-background image.

Request example

Example
{
  "image_file_id": "123456789",
  "industry_type": "portrait",
  "quality_type": "original",
  "trim_transparent_background": true
}

Request fields

FieldTypeRequiredNotes / allowed values
image_file_idstringyesFile ID of the image to cut out; supports jpg, jpeg, png, webp, and heic.
industry_typeenumnoportrait, product, general, and compatible aliases. Default: portrait.
quality_typeenumnooriginal, fast, and compatible aliases. Default: original.
trim_transparent_backgroundbooleannoTrim extra transparent canvas around the cutout. Default: false.

Response data fields

FieldTypeRequiredNotes / allowed values
task_idstringyesAsync task ID.
statusTaskStatusyesUsually Processing when the task is created.
status_urlstringyesURL for polling task status.
result_urlstringyesURL for reading task results.
created_atstring(date-time)noTask creation time.

Image upscale

POST/v1/images/upscale

Create an image upscaling task to improve resolution and clarity.

Request example

Example
{
  "image_file_id": "123456789",
  "method": "ai_super_resolution",
  "preset": "hd",
  "type": "2X",
  "enhance_face": true,
  "enhance_quality": true
}

Request fields

FieldTypeRequiredNotes / allowed values
image_file_idstringyesFile ID of the image to upscale; supports heic, jpg, png, and webp.
methodenumnoai_super_resolution, super_resolution, or enhance. Default: ai_super_resolution.
presetenumnoauto or hd. Default: auto.
typestringnoUpscale factor. Default: 2X.
enhance_facebooleannoEnhance face details.
enhance_qualitybooleannoEnhance overall image quality.
enhance_textbooleannoEnhance text clarity.

Response data fields

FieldTypeRequiredNotes / allowed values
task_idstringyesAsync task ID.
statusTaskStatusyesUsually Processing when the task is created.
status_urlstringyesURL for polling task status.
result_urlstringyesURL for reading task results.
created_atstring(date-time)noTask creation time.

PDF watermark removal

POST/v1/pdfs/remove-watermark

Create a PDF watermark removal task with structured or AI reconstruction mode.

Request example

Example
{
  "pdf_file_id": "123456789",
  "mode": "editable"
}

Request fields

FieldTypeRequiredNotes / allowed values
pdf_file_idstringyesFile ID of the PDF to process.
modeenumnoeditable for structured watermark removal; ai for page-by-page image reconstruction. Default: editable.

Response data fields

FieldTypeRequiredNotes / allowed values
task_idstringyesAsync task ID.
statusTaskStatusyesUsually Processing when the task is created.
status_urlstringyesURL for polling task status.
result_urlstringyesURL for reading task results.
created_atstring(date-time)noTask creation time.

Limits and billing

Upload limits

FieldTypeRequiredNotes / allowed values
Files per batchintegerfixed limitUp to 500 files.
Single file sizebytesfixed limitUp to 2 GB.
Multipart thresholdbytesfixed ruleWith upload_mode=auto, files larger than 5 MB usually receive upload_urls; simple explicitly asks for one upload_url.
Upload URL lifetimedurationfixed ruleupload_url / upload_urls are valid for about 2 hours; call batch-create again after expiration.
Download URL lifetimedurationfixed ruledownload_url is valid for about 24 hours; query result_url again after expiration.
  • Large customer accounts may have a custom API multiplier. Actual billing is based on the server-side multiplier snapshot captured when the task is created.
  • Image watermark removal default API price: 2 credits per image.
  • Background removal default API price: 10 credits per image.
  • Image upscale default API price: 6 credits per image.
  • PDF watermark removal editable mode default API price: 4 credits per file.
  • PDF watermark removal AI mode default API price: 2 credits per page.
  • GPT Image 2 watermark-free mode default API price: 5.34 credits per output image.
  • No separate API usage ledger is created; credit records remain the source of truth.
  • Web and API tasks share the same in-flight pool: Pending + Processing <= 20.
  • The first version only supports asynchronous APIs.
  • See the full tool pricing table.