Menu
Async API

Pilio API Documentation

Use permanent API keys to create asynchronous image processing, PDF watermark removal, and GPT Image 2 tasks. API calls reuse your existing Pilio credits and task limits.

Basics

Authentication

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

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.

# 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.

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

File upload and download

Image editing and image/PDF processing 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
{
  "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_intentenumnotemporary or permanent; image/PDF processing inputs usually use temporary.
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
{
  "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.

{
  "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
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
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.

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

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 does not maintain official SDKs yet. Use the OpenAPI JSON as the source of truth and generate a thin client that wraps authentication, response envelopes, polling, and downloads.

Tool APIs

GPT Image 2

POST/v1/images/gpt-image-2/generations

Create a GPT Image 2 text-to-image task.

Request example

{
  "prompt": "A cinematic product photo of an orange perfume bottle",
  "aspect_ratio": "3:2",
  "output_count": 2,
  "quality": "high"
}

Request fields

FieldTypeRequiredNotes / allowed values
promptstringyesGeneration or editing prompt, up to 32000 characters.
negative_promptstringnoNegative prompt, up to 32000 characters.
aspect_ratioenumrequired for generation; optional for edits1: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.
resolutionenumno0.5K, 1K, 2K, or 4K.
qualityenumnolow, medium, or high.
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.

POST/v1/images/gpt-image-2/edits

Create a GPT Image 2 image editing task with 1-16 reference images.

Request example

{
  "prompt": "Turn this reference into a studio product photo",
  "image_file_ids": ["123456789", "123456790"],
  "aspect_ratio": "auto",
  "quality": "medium"
}

Request fields

FieldTypeRequiredNotes / allowed values
image_file_idsstring[]yesReference image file IDs, 1-16 items; supports jpg, jpeg, png, and webp.
promptstringyesGeneration or editing prompt, up to 32000 characters.
negative_promptstringnoNegative prompt, up to 32000 characters.
aspect_ratioenumrequired for generation; optional for edits1: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.
resolutionenumno0.5K, 1K, 2K, or 4K.
qualityenumnolow, medium, or high.
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

{
  "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

{
  "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

{
  "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

{
  "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.
  • Credits are deducted from your normal Pilio credit balance.
  • Image watermark removal costs 1 credits per image.
  • Background removal costs 1 credits per image.
  • Image upscale costs 3 credits per image.
  • PDF watermark removal editable mode costs 2 credits per file.
  • PDF watermark removal AI mode costs 1 credits per page.
  • GPT Image 2 watermark-free mode costs 2 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.