LEAPI Documentation

Let's Enhance makes your images better in sense of resolution, weight and colours. Our image rendering API utilizes the latest AI technologies to eliminate image compression artifacts, upsample, retouch, resize and encode images to align every single image to your specific quality requirements.

We are constantly working on improving of our API and came up with decision to completely rework it. This documentation represent current version API, it's stable, used but lot of customers, but a bit complex. We will cover everything you need to get Let’s Enhance running and start developing your Let’s Enhance integration.

The Quick start will guide you how to get api key and process your first image.

Check our Presets for a list of available operations.

Quick start

This development quickstart should get you up and running with the Let's Enhance API. In most cases, that should be enough, however, more in-depth information can be found at API In-depth

Keep reading, we will provide request samples once you need it.

Get API key

Open Let's Enhance account profile , hit the Request API Key and follow the instructions. For this guide, we will assume your API key is 1234567890

Authentication

The Let's Enhance API uses an API key to authenticate requests. You can view and manage your API key in the Let's Enhance account profile. Authentication to the API is performed via HTTP Headers. Provide your API key as the X-API-KEY value. You do not need to provide a password.

Process your image

Let's take the reference image to our right and enhance it.

The resolution of our reference is 900 x 600 pixels. It is underexposed and it is missing details as a result of compression. We're going to clean it from compression artifacts, restore details, increase its resolution, correct colors, and encode it for output using one of our presets.

Reference image

image
https://letsenhance.io/docs/assets/samples/burger.jpg

Making a request

To process any image, you should make a POST request to the endpoint with header X-API-KEY being set to API key you got on authentication (assume it's 1234567890), and JSON body, describing input image with operations to apply.

Let's try it out using the request body below. Submitting that request will send the image you specified to processing and will create a pipeline.

Depending on image size, processing may take some time, we will describe it better in other sections. For now, you need to read the response of your request.

API endpoint

https://api.letsenhance.io/v1/pipeline

icon

don't forget to set the correct X-API-KEY header

Request body

curl -X POST "https://api.letsenhance.io/v1/pipeline" \
     -H "X-API-KEY: 1234567890" \
     -H "Content-Type: application/json" \
     -d '
{
    "source": {
        "http": {
            "url": "https://letsenhance.io/docs/assets/samples/burger.jpg"
        }
    }, 
    "operations": [
        {
            "op": "preset/marketplace",
            "width": 1800,
            "height": 1200,
            "restoration_level": 4,
            "lightai_intensity": 1.0,
            "toneai_intensity": 0.5,
            "image_format": "JPEG",
            "quality": 75
        }
    ],
    "sink": {
        "temp_store": true
    }
}

Detailed description of request bodies can be found here

Reading response

Once you have made the request to https://api.letsenhance.io/v1/pipeline you will get a response, containing information about your image.

There are two key things to look after

  • status field – if everything is ok, it will be ACCEPTED. In case of some errors, it will be REJECTED and you will not be withdrawn with a credit.
  • pipeline.id field – only if the status is ACCEPTED describes id of your request, save it, you will need it to collect the result. In our case, it's 26082838

Response body

{
    "status": "ACCEPTED",
    "pipeline": {
					...
        },
        "id": 26082838,
        "notify_url": null
    }
}

Detailed description of response can be found here

Retrieve the result

To get pipeline status, you need to submit GET request endpoint https://api.letsenhance.io/v1/pipeline/<pipeline.id> with header X-API-KEY being set to API key you got on authentication (assume it's 1234567890) and <pipeline.id> replaced with value you get during previous step (26082838)

The irst field you must check is status where there are three possible values you should take into account

"status": "PROCESSING" - image is still processing, you should wait a bit and make GET request again.

"status": "DONE" - your image is processed and you can grab the result url from field results[0].output_object.temp_url That link contains processed image, we store it for 24 hours once it's done. In order to get processed image simply grab it with GET (see save the result section).

"status": "ERROR" - something bad happened, sometimes it's enough just to process it again. It can also be due to bad image format field.

errors may provide details about what has gone wrong, but it's intent is to help with troubleshooting, not to show user-friendly messages.

Pipeline request body

curl -X GET https://api.letsenhance.io/v1/pipeline/26082838 -H "X-API-KEY: 1234567890"

Pipeline response body

{
    "pipeline": {
        "id": 26082838,
        ...
        "status": "DONE",
        "results": [
            {
                "created_at": "2021-04-06T11:22:57.72606",
                "input_object": {
										...
                },
                "output_object": {
										...
										"tmp_url": "https://s3.amazonaws.com/leapi-tmp-us-east-1/p/26082838/1200x727-1_KThGB7.jpg?response-content-type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIFU5PY2YVSAGMK3Q%2F20210406%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210406T112257Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=c984b3f6d237031bc9300abdb87963be8b5712bedd3dafc8568ac4758bbefe26",
                }
            }
        ],
        "notify_url": null,
        "operations": [
				....
        ],
        "started_at": "2021-04-06T11:22:53.664904",
        "finished_at": "2021-04-06T11:22:57.940067",
        "submitted_at": "2021-04-06T11:22:53.610298"
    }
}

We poll the request periodically to get fresh status. Its a convenient method while working on a few requests, but it isn't ideal as you scale up. Webhooks are recommended once you consider developing your integration.

Save the result

Once status is DONE, you should grab the resulting image via url from the field results[0].output_object.temp_url, like:

Saving a processed image

curl -X GET "https://s3.amazonaws.com/leapi-tmp-us-east-1/p/26082838/1200x727-1_KThGB7.jpg?response-content-type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIFU5PY2YVSAGMK3Q%2F20210406%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210406T112257Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=c984b3f6d237031bc9300abdb87963be8b5712bedd3dafc8568ac4758bbefe26"

Image result

image

Webhooks

To use webhook, callback in other words, you should modify POST request from our initial request body

All you need is to set notify_url field to point to your webserver. This value may differ for each request, allowing you even to put some own data in it. This url can be http or https. e.g:

Once image is processed, we will send a POST request to endpoint you specified with notify_url.

Webhook retry logic

icon

If your server responds with error (status code ≥ 400), next retries will occur in the following order 1st attempt 3 minutes after first webhook wasn't acknowledged 2nd attempt 6 minutes after previous attempt 3rd attempt 10 minutes after previous attempt If all attempts are not acknowledged, the only way to get the processing status is by querying pipeline endpoint below https://api.letsenhance.io/v1/pipeline/<pipeline.id>

curl -X POST "https://api.letsenhance.io/v1/pipeline" \
     -H "X-API-KEY: 1234567890" \
     -H "Content-Type: application/json" \
     -d '
{
    "source": {
        "http": {
            "url": "https://letsenhance.io/docs/assets/samples/burger.jpg"
        }
    },
    "notify_url": "https://your.domain/path/to/webhook",
    "operations": [
        {
            "op": "preset/marketplace",
            "width": 1800,
            "height": 1200,
            "restoration_level": 4,
            "lightai_intensity": 1.0,
            "toneai_intensity": 0.5,
            "image_format": "JPEG",
            "quality": 75
        }
    ],
    "sink": {
        "temp_store": true
    }
}

API In-depth

API Reference

The Let's Enhance API is organized around REST. It accepts JSON-encoded request bodies, and returns JSON-encoded responses.

Our API provides various automated image processing workflows to enhance images. It supports image URLs as inputs, which are requested via JSON objects that contain the image processing operations. It is asynchronous, allowing you to process multiple images at a time asynchronously without having to block.

Base URL

https://api.letsenhance.io/v1/pipeline/

By default, the Let's Enhance API Docs demonstrate using curl to interact with the API over HTTP.

API Requests

Sending requests

Processing images with the Let's Enhance API is done through submitting POST requests for image processing. Each successful POST request will have a unique request identifier (id) under the response body, which can later be used to retrieve a processed image.

Let's take the reference image to our right and enhance it. The resolution of our reference is 900 x 600 pixels. We're going to clean it from compression artifacts, restore details, increase its resolution, correct colors, and encode it for output using one of our presets that bundles different types of core operations into one simple operation. We will define the image to be upsampled above its original size with a desired output resolution of 1800 x 1200. This will be done by setting up the desired parameters on the JSON body.

icon

Insert an image url we wish to process and define the type of image processing that will take place. For the reference image above, we're going to use our marketplaces preset and set our desired upsampling by giving the image a larger resolution than its initial resolution. To do so, we will use our width and height parameters under preset/marketplace. We also will set the restoration_level to 4.

icon

Configure the encoder and set the desired quality factors for encoding. This is done through the image_format field. Let's set it to JPEG, and set the quality to 75.

icon

Set temp_store as 'true' to generate a temporary download link

icon

All of our presets are bundles of different core image processing operations, wrapped into one simple operation.

Reference image

image
https://letsenhance.io/docs/assets/samples/burger.jpg
icon

Compression caused poor color and brightness, as well as loss of some of the details

Request body

curl -X POST https://api.letsenhance.io/v1/pipeline \
-H "X-API-KEY: yourkey" \
-H "Content-type: application/json" \
-d @filename.json \

Request fields

source (object) determines the source of the image

http (object) input image source type

url (string) image URL (supports multiple URLs)

notify_url (string) Receive a notification when the images in the request have been processed. This notifies the caller with a POST and pipeline id via webhook point to your webserver (see webhooks).

operations indicates the operations used

op (string) determines the image processing operation

height (integer) desired output height in pixels

width (integer) desired output width in pixels

icon

The aspect ratio of the input image will always be perserved on output. This means the API will never stretch or squeeze an image beyond its initial aspect ratio.

sink the output source of an image request

temp_store (boolean) to generate a temporary URL valid for 24 hour

JSON object

{
    "source": {
        "http": {
            "url": "https://letsenhance.io/docs/assets/samples/burger.jpg"
        }
    },
    "notify_url": "https://your.domain/path/to/webhook",
    "operations": [
        {
            "op": "preset/marketplace",
            "width": 1800,
            "height": 1200,
            "restoration_level": 4,
            "lightai_intensity": 1.0,
            "toneai_intensity": 0.5,
            "image_format": "JPEG",
            "quality": 75
        }
    ],
    "sink": {
        "temp_store": true
    }
}

Response fields

icon

POST requests will return a response that a pipeline has been submitted with status "ACCEPTED" by default. The response contains a unique pipeline id that will be used to retrieve the results.

pipeline (object) indicates the request is part of a pipeline

id (integer) id of async request, used for retrieving processing results

JSON object

{
    "status": "ACCEPTED",
    "pipeline": {
        "source": {
 ...
        },
        "id": 26082838,
        "notify_url": null
    }
}

Retreiving results

Request body

icon

The unique pipeline id we recieved on our response above, is used to retrieve processing results of a specific async request. Sending a GET request with a pipeline id will return a JSON object with the image metadata along with a temporary URL of the processed image.

curl -X GET https://api.letsenhance.io/v1/pipeline/26082838 \
-H "X-API-KEY: yourkey" \

Get response fields

pipeline (object) indicates the request is part of a pipeline

id (integer) id of async request

sink the output source of an image request

temp_store (boolean) indicates whether a temporary URL will be generated

errors (int) error type if exists

source (object) determines the source of the image

http (object) input image source type

url (string) input image URL (supports multiple URLs)

status (string) status of the async request. Options:

  • PROCESSING — Request is processing
  • ERROR — Request finished and failed
  • DONE — Request finished and succeeds

results processing results metadata

created_at (timestamp) indicates the time the metadata was parsed

ext (string) filetype extension

input_object input image metadata

mps (float) input megapixel count

url (string) input image URL

mime (string) mime type

size (integer) input image dimensions in pixels (width, height)

width (integer) input image width in pixels

height (integer) input image height in pixels

format (string) image format

s3_key (string) input s3 key (null by default)

tmp_url (string) input image temporary storage (null by default)

basename (string) file name without its filetype extension

filename (string) file name with its filetype extension

interpret

s3_bucket

s3_key_prefix

output_object output image metadata

ext (string) filetype extension

mps (float) output megapixel count

url (string) output image URL

mime (string) mime type

size (integer) image dimensions in pixels (width, height)

width (integer) output image width in pixels

height (integer) output image height in pixels

format (string) image format

s3_key (string) input s3 key (null by default)

tmp_url (string) output image temporary storage

basename (string) file name without its filetype extension

filename (string) file name with its filetype extension

interpret (string) output colorspace interpretation

s3_bucket (string) s3 output bucket (leapi-tmp-us-east-1 by default)

s3_key_prefix

started_at (timestamp) the time the pipeline started processing

finished_at (timestamp) the time the pipeline finished processing

submitted_at (timestamp) the time of pipeline submission

JSON object

{
    "pipeline": {
        "id": 27312832,
        "sink": {
            "temp_store": true
        },
        "error": null,
        "errors": [],
        "source": {
            "http": {
                "url": [
                    "https://letsenhance.io/docs/assets/samples/burger.jpg"
                ]
            }
        },
        "status": "DONE",
        "results": [
            {
                "created_at": "2021-04-26T13:46:09.145864",
                "input_object": {
                    "ext": "jpg",
                    "mps": 0.54,
                    "url": "https://letsenhance.io/docs/assets/samples/burger.jpg",
                    "mime": "image/jpeg",
                    "size": [
                        900,
                        600
                    ],
                    "width": 900,
                    "format": "JPEG",
                    "height": 600,
                    "s3_key": null,
                    "tmp_url": null,
                    "basename": "burger",
                    "filename": "burger.jpg",
                    "interpret": null,
                    "s3_bucket": null,
                    "s3_key_prefix": ""
                },
                "output_object": {
                    "ext": "jpg",
                    "mps": 2.16,
                    "url": null,
                    "mime": "image/jpeg",
                    "size": [
                        1800,
                        1200
                    ],
                    "width": 1800,
                    "format": "JPEG",
                    "height": 1200,
                    "s3_key": "p/27312832/burger_j63Bv5.jpg",
                    "tmp_url": "https://s3.amazonaws.com/leapi-tmp-us-east-1/p/27312832/burger_j63Bv5.jpg?response-content-type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIFU5PY2YVSAGMK3Q%2F20210426%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210426T134609Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=8b821e5f2d14ef6358921bef3212801cb309d6caa168a4823e05db427f8b5e77",
                    "basename": "burger_j63Bv5",
                    "filename": "burger_j63Bv5.jpg",
                    "interpret": "srgb",
                    "s3_bucket": "leapi-tmp-us-east-1",
                    "s3_key_prefix": ""
                }
            }
        ],
        "notify_url": "https://your.domain/path/to/webhook",
        "operations": [
            {
                "op": "preset/marketplace",
                "width": 1600,
                "height": 900,
                "restoration_level": 4,
                "lightai_intensity": 1.0,
                "toneai_intensity": 0.5,
                "image_format": "JPEG",
                "quality": 75
            }
        ],
        "started_at": "2021-04-26T13:46:01.358819",
        "finished_at": "2021-04-26T13:46:09.361341",
        "submitted_at": "2021-04-26T13:46:01.309535"
    }
}

Presets

Our presets contain ready-for-use recipes by calling multiple image processing operations, hand-tailored to specific verticals. Each preset contains different variants for rapid testing at scale to find the highest rate of processing consistencies for your images. Under the hood, there are deep neural networks that have been built from the ground up to recover low quality images.

Restoration Levels

Each preset has a restoration_level associated to it, ranging from 1 being to lightest in intensity, to 10, being the strongest in intensity.

Knowing which restoration level to apply depends on the condition of the input images, primarily in resolution and how badly compressed they are. The higher the restoration_level, the more aggressive the upsampling approach will be.

The higher the image quality, the lower the restoration_level.

The lower the image quality, the higher the restoration_level.

We purposely selected very low quality input images for all of our comparisons as baselines. This includes low resolution (< 1 megapixel) with heavy JPEG compression.

image
icon

The lower the input resolution, the more difficult the upsampling process is. We recommend you to test all presets and their variants. This will increase the chances of finding consistent, quality results.

icon

All image comparisons under this section are further optimized and served through our end-to-end imaging product. Drop us a line at sales@letsenhance.io for more info

Real Estate

Preset fields:

op (string) - operation name preset/realestate

width (integer) - output width in pixels

restoration_level (integer) - intensity of detail restoration (see here)

height (integer) - output height in pixels

lightai_intensity (float, 0.1 - 0.99) - color and brightness correction

toneai_intensity (float, 0.1 - 0.99) - image tones (contrast, shadows)

image_format (string JPEG, PNG) - sets the image filetype

quality (integer) - sets the encoding quality of a JPEG image.

icon

Sample for realestate preset

JSON Body

{
    "op": "preset/realestate",
    "width": 1600,
    "height": 900,
    "restoration_level": 4,
    "lightai_intensity": 1.0,
    "toneai_intensity": 0.5,
    "image_format": "JPEG",
    "quality": 75
}

Input Image 960 x 540, 566 kB

image

Output Image 1600 x 900 , 240 kB

image
image
image

Printing

Preset fields:

op (string) - operation name preset/print

width (integer) - output width in pixels

height (integer) - output height in pixels

restoration_level (integer) - intensity of detail restoration (see here)

tone_intensity (float, 0.1 - 0.99) - image tones (contrast, shadows)

lightai_intensity (float) 0.1 - 0.99 - color and brightness correction

dpi (integer) - output DPI

image_format (string JPEG, PNG) - sets the image filetype

quality (integer) - sets the encoding quality of a JPEG image.

icon

Sample for printing preset

JSON Body

{
    "op": "preset/print",
    "width": 1600,
    "height": 1065,
    "restoration_level": 2,
    "lightai_intensity": 1.0,
    "toneai_intensity": 0.5,
    "dpi": 300,
    "image_format": "JPEG",
    "quality": 85
}

Input Image 1080 x 719 , 67 kB

image

Output Image 1600 x 1065 , 67 kB

image

Zoomed Input

image

Zoomed Output

image

Marketplace

Preset fields:

op (string) - operation name preset/marketplace

width (integer) - output width in pixels

height (integer) - output height in pixels

restoration_level (integer) - intensity of detail restoration (see here)

lightai_intensity (float, 0.1 - 0.99) - color and brightness correction

tone_intensity (float, 0.1 - 0.99) - image tones (contrast, shadows)

image_format (string JPEG, PNG) - sets the image filetype

quality (integer) - sets the encoding quality of a JPEG image.

JSON Body

{
    "op": "preset/marketplace",
    "width": 1200,
    "height": 1600,
    "restoration_level": 2,
    "lightai_intensity": 1.0,
    "toneai_intensity": 0.5,
    "image_format": "JPEG",
    "quality": 75
}
icon

Sample for marketplace preset

Input Image 450 x 600 , 76 kB

image

Output Image 1200 x 1600, 76 kB

image

Management API

Monitor API Usage

API quotas protect the Let's Enhance infrastructure from excessive API requests. Traffic is blocked when the level of requests reaches the monthly API quota level or a per-user rate limit.

Your monthly usage and quotas can be directly checked via through the following URL

https://api.letsenhance.io/v1/me/usage/

Request body

curl -X GET "https://api.letsenhance.io/v1/me/usage/" \
     -H "X-API-KEY: 1234567890" \
icon

Unused credits do not roll-over and will reset at the beginning of each month

Quota Costs

Every API request made counts the amount of images processed under a given request. For example, an API request with 3 URLs will count 3 credits. Invalid requests will not incur any quota cost.

Rate Limits

icon

A rate limiter that limits the number of requests received by the API within any given minute.

The Let's Enhance API employs a number of safeguards against bursts of incoming traffic to help maximize its stability. Users who send many requests in quick succession may see error responses that show up as status "REJECTED" Too many requests. Rate limit exceeded.

Rate limit message

{
    "status": "REJECTED",
    "reason": "Too Many Requests. Rate limit exceeded."
}

Edge Cases — TBD

FAQ

Supported Images

Our API supports images file types that are either JPEG, TIFF, PNG, BMP, or WEBP.