EyeQ Docs

API reference

Complete endpoint and query parameter reference for Perfectly Clear Web API v2

This page provides the complete endpoint and query parameter reference for Perfectly Clear Web API v2.

Base URL

https://api.perfectlyclear.io/v2

Authentication

Send your API key in the request header:

X-API-KEY: <your_api_key>

Endpoints

EndpointMethodDescription
/uploadGETGet a pre-signed upload URL and fileKey
/pfcGETStart a correction job
/status/{jobID}GETCheck correction job status
/presetsGETList available presets
/presets/POSTCreate a preset upload request
/presets/{presetId}GETGet a preset
/presets/{presetId}DELETEDelete a preset

Query parameters

GET /upload

ParameterTypeRequiredDefaultDescription
fileTypestringNoimageFile type for the upload request. Use image or video.

GET /pfc

Resize-related settings are mutually exclusive. Use only one resize dimension strategy per request (width, height, long, short, or scale).

ParameterTypeRequiredDefaultAllowed / RangeDescription
fileKeystringYesID of the uploaded file returned by /upload.
fileTypestringNoimageimage, videoFile type for correction. Must match the uploaded file type.
presetstringNoAI preset selectionAny preset name or nonePreset to apply. Use none to skip correction and perform resize/output-only operations.
cachebooleanNotruetrue, falseReuse existing corrected output for identical settings when available.
outputTypestringNooriginaljpg, png, originalOutput format. original keeps source format when supported.
resizestringNoautoauto, general, smallDetailsUpscaling mode used when resizing is requested.
widthintegerNo32 to 10000Target width in pixels. Height is derived from aspect ratio.
heightintegerNo32 to 10000Target height in pixels. Width is derived from aspect ratio.
longintegerNo32 to 10000Target long edge in pixels.
shortintegerNo32 to 10000Target short edge in pixels.
scaleintegerNoInteger percentScale percentage. Example: 200 doubles width and height.
outputQualityintegerNo9040 to 100JPEG quality setting. Ignored for non-JPEG output.
autocropbooleanNofalsetrue, falseEnable auto-cropping.
autocropDetectOnlybooleanNofalsetrue, falseReturn crop coordinates without applying crop. Requires autocrop=true.
autocropSizestringNoWorkbench valueHead size factor for autocrop.
autocropXstringNoWorkbench valueRelative horizontal head offset for autocrop.
autocropYstringNoWorkbench valueRelative vertical head offset for autocrop.
cropARWstringNoWorkbench valueCrop aspect ratio width component.
cropARHstringNoWorkbench valueCrop aspect ratio height component.
autocropTopHeadGapstringNoPositive value to enableTop-of-head gap target for autocrop. Zero or negative disables this behavior.
skipstringNoclipartclipart, legacy, noneNon-photo skip mode. Ignored when AI preset selection is active.
removeGlaresbooleanNofalsetrue, falseEnable glasses glare detection and removal.
removeBackgroundbooleanNofalsetrue, falseEnable background removal. If output type is omitted, output is PNG with transparency.
bgColorstringNotransparentHex with # or named colorBackground color used when removeBackground=true.
preserveMetadatabooleanNotruetrue, falsePreserve source EXIF metadata, especially for upscaling/background-removal workflows.
updateThumbnailbooleanNofalsetrue, falseRegenerate embedded thumbnail metadata.
includeDetectionDatabooleanNofalsetrue, falseInclude scene detection, face detection and other image data in the /status output.

POST /presets/

Uploading a custom preset is a two-step process:

Step 1 — Request an upload URL

Send a POST request with the preset metadata. The API returns a pre-signed uploadUrl and a presetId.

Request body (JSON):

{
  "name": "My Custom Preset",
  "description": "Portrait retouching for studio shots"
}

Example:

curl -X POST "https://api.perfectlyclear.io/v2/presets/" \
  -H "X-API-KEY: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Custom Preset", "description": "Portrait retouching"}'

Response:

{
  "presetId": "abc123",
  "uploadUrl": "https://storage.example.com/presigned-url..."
}

Step 2 — Upload the preset file

Use the uploadUrl from Step 1 to upload your preset file with an HTTP PUT request. No API key is required for this request — authentication is embedded in the pre-signed URL.

curl -X PUT "<uploadUrl>" \
  --upload-file /path/to/your/preset.pcp

Once the upload completes, the preset is available in your account and can be referenced by name in /pfc requests via the preset parameter.

GET /presets

ParameterTypeRequiredDefaultDescription
limitintegerNo20Maximum number of presets returned.
offsetintegerNo0Number of presets to skip before returning results.

Path parameters

EndpointParameterTypeDescription
/status/{jobID}jobIDstringCorrection job identifier returned in statusEndpoint.
/presets/{presetId}presetIdstringPreset identifier.

Status responses

GET /status/{jobID} can return these states:

  • PENDING
  • PROCESSING
  • COMPLETED
  • FAILED
  • REJECTED

The /status endpoint will also return different HTTP status codes to indicate the status of the job. These include:

  • 200 the job is still processing
  • 302 the job is complete and the corrected file is ready to download

When the 302 status is returned from the /status endpoint, the location header will contain the URL to download the corrected file. You can use curl -L to follow that redirect and download the corrected file. Other tools will redirect automatically, which makes it simple to check the status and also retrieve the corrected file in one call. You can also prevent this redirect behavior by including the noRedirect=true query parameter in the status call. This will allow you to check the status without automatically downloading the file when it is ready.

Along with these status values, the message will also contain statusText that explains any errors or the processing in a little more detail. Once the job is COMPLETED, the status call will return a correctedFile parameter in the reply, like this:

{
   "status":"COMPLETED",
   "_id":"1234512345",
   "statusText":"done",
   "createdAt":"2023-02-16T23:13:43.821Z",
   "updatedAt":"2023-02-16T23:13:51.831Z",
   "correctedFile":"https://outputdomain.com/images/pfc-54321-12345-123451234_corrected_scene.jpg"
}

If you included includeDetectionData=true in your original correction request, the status response will also include a detectionData object with AI-detected scene, face, and other image data. For example:

{
  "_id": "69d694003274e636c06e4384",
  "status": "COMPLETED",
  "statusText": "",
  "code": 0,
  "correctedFile": "https://outputdomain.com/images/pfc-54321-12345-123451234_corrected_scene.jpg",
  "createdAt": "2025-04-08T17:44:32.164Z",
  "updatedAt": "2025-04-08T17:44:39.004Z",
  "usage": {
    "size": "MEDIUM",
    "imageCorrectionCount": 1,
    "imageResizeCount": 0,
    "classicResizeCount": 0,
    "glaresDetectorCount": 0,
    "videoCorrectionCount": 0,
    "removeBackgroundCount": 0,
    "removeGlaresCount": 0,
    "autoCropCount": 0,
    "removeGlaresTotalCount": 0
  },
  "aiserver": true,
  "timeTaken": 1.56,
  "originalDimensions": {
    "width": 2380,
    "height": 3597
  },
  "detectionData": {
    "facesCount": 1,
    "faces": [
      {
        "confidence": 94,
        "angle": 2,
        "blink": 8,
        "smile": 67,
        "yawAngle": 0,
        "left": 971,
        "top": 431,
        "width": 497,
        "height": 581,
        "leftEye": {
          "x": 1333.879150390625,
          "y": 620.4785766601562
        },
        "rightEye": {
          "x": 1088.085693359375,
          "y": 608.4886474609375
        }
      }
    ],
    "scene": 8,
    "noise": "unknown",
    "redEye": "disabled",
    "warnings": [],
    "message": "",
    "status": "ok"
  }
}

WEB-API Version 2 built on 02-26-2026.

Copyright © 2026 EyeQ Imaging Inc. All rights reserved.

On this page