API Reference

The API is hosted at optimize.exactlywww.com and may be accessed by either HTTPS or HTTP (HTTPS is preferred). This document describes how to interact with the API directly, and will give examples with the curl utility. All requests to the API must use the POST method.

To access the API using PHP, please use our PHP library. If you have implemented access to the API in another programming language, I would be happy to feature your code examples/libraries here for others to use.

Authentication – /verify/

To use the API, you must provide a valid API key. You can get an API key if you do not already have one.

All data sent to the API must be sent via POST variables, and the API key is transmitted as api_key. The simplest request that can be used for testing is to POST your key to https://optimize.exactlywww.com/verify/

There are three possible responses (all are JSON encoded, but you can just check the response for the presence of these values):

  • “great” = verification successful
  • “exceeded” = indicates a valid key with no remaining image credits. This can be useful to stop optimization attempts when doing batch operations.
  • “invalid” = indicates that the key is not valid (not found)

It is not required to send a request to /verify/ for each image, as the optimization endpoint will authenticate all API keys. However, it IS recommended to periodically test an API key to make sure it is still valid so that your program is not sending unnecessary optimization requests. The WordPress plugin checks approximately once per hour, but only when optimizations are being attempted.

Try it out with curl (the key ‘abc123’ will always return ‘great’):

curl --data api_key=abc123 https://optimize.exactlywww.com/verify/

Usage – /quota/

If you are developing software that will be used by many people (or at least you hope so), it is useful to display the number of credits available. This can be done by sending a request nearly identical to the authentication request. The only difference is that you send it to https://optimize.exactlywww.com/quota/

The response is a simple text string with three numbers, like “5000 3221 23”. The three values indicate the following:

  1. The number of images allowed per month. A value of 0 indicates the user is on a metered plan (they will be billed at the end of the month and do not have a defined monthly quota) OR that the user does not have a monthly plan and has pre-paid for a certain number of credits instead.
  2. The number of images optimized in this billing cycle. A negative value indicates how many credits are remaining when using prepaid options, whereas a positive value will indicate how many images they have optimized on their monthly subscription.
  3. The number of days until the next payment, IF they have a subscription.

Thus, “0 -3000 0” is an example of someone who prepaid for 3,000 credits whereas “0 1000 20” would show someone who has used 1,000 credits on a metered subscription that will be billed in 20 days. The older PayPal subscriptions are the only ones that will have a defined monthly quota like “20000 2348 11”, although we do still allow folks to create new PayPal subscriptions if they choose (not very many do).

You can try this with curl (the key ‘abc123’ will return an auto-generated response):

curl --data api_key=abc123 https://optimize.exactlywww.com/quota/

Optimization – /

There are only two required pieces of information to optimize an image: api_key and a file to optimize. As before, this information must be sent in a POST request. The API returns the optimized image directly as the response body, where an empty (zero-byte) response indicates no additional savings were possible. These requests should be sent to https://optimize.exactlywww.com/v2/

The basic example with curl, assuming there is a file named ‘image_to_optimize.jpg’ in the current directory, would be as follows:

curl --form api_key=abc123 --form file=@image_to_optimize.jpg https://optimize.exactlywww.com/v2/ > optimized_image.jpg

The file type of the optimized file should be checked to ensure that a valid image was returned before replacing the original image with the optimized one, since an empty response is used to indicate no additional savings was achieved (or you could just check for an empty file).

Additional request options

There are several other options available to preserve metadata, like EXIF and copyright info, as well options for lossy compression, webp image generation, and image conversion:

  • filename: The API logs all images optimized so that API users may view their history at any time independently of whatever plugin or platform they are using. This allows a developer to log the full file-system path for better diagnostics and debugging. If a filename parameter is not provided, the API will simply log the name of the file parameter, like ‘image_to_optimize.jpg’ instead of something more exact like ‘/var/www/html/images/image_to_optimize.jpg’.
  • metadata: 1 = preserve all metadata possible, 0 = strip all metadata
  • height: Specify a number of pixels to resize the height of a WebP image (webp = 1). Use this to avoid using resized (and compressed) JPG resizes to generate a WebP image that will result in further quality loss.
  • width: Specify a number of pixels to resize the width of a WebP image (webp = 1). Use this to avoid using resized (and compressed) JPG resizes to generate a WebP image that will result in further quality loss.
  • crop: 1 = constrain/crop WebP image (webp = 1) to the exact dimensions specified in width and/or height. 0 = scale the image to the lower of width or height.
  • lossy: 1 enables higher compression with minimal quality loss for JPG, PNG, and PDF files, 0 uses standard lossless compression for zero quality loss.
  • lossy_fast: 1 enables much faster compression, but average savings is 10-20% less than regular lossy mode, 0 uses regular lossy when lossy = 1.
  • compress: 1 enables extra lossless compression for PNG images using the zopfli algorithm. It is very slow and should be used only if processing time is not an issue.
  • convert: 1 enables conversion mode for JPG to PNG, PNG to JPG or GIF to PNG. The API will only convert PNG images that have alpha/transparency if jpg_fill is specified (see below). Animated GIF files will do something unexpected when attempting to convert to PNG, most likely taking just the first frame of the image. Thus it is recommended to check for animated GIF files on the “client” system before attempting to upload to the API.
  • jpg_fill: This is only used when convert = 1 and must be in HTML hexadecimal notation (#ffffff = white). Only used to set the background/fill color for PNG images that are converted to JPG. Leave empty to skip conversion for transparent PNG images.
  • quality: Used when creating WebP files and when processing PNG images with convert = 1. Accepts a value from 1-100. Default is 82.
  • webp: 1 enables WebP generation, and will always return a WebP file even if it is not smaller than the original. It is up to the client software to determine if it is desirable to keep all WebP images received, or only those smaller than the original. This option runs in exclusion of all others, and because not all browsers support the WebP format you should submit two API requests when using WebP: a request with webp=1 to get the .webp file, and then another request with webp=0 to make sure the original image gets optimized too.

As a more complete example, here is what it would look like with all options specified:

curl --form filename=/var/www/image_to_optimize.jpg --form convert=0 --form metadata=1 --form api_key=abc123 --form jpg_fill=#ffffff --form quality=92 --form compress=0 --form lossy=0 --form lossy_fast=0 --form webp=0 --form file=@image_to_optimize.jpg https://optimize.exactlywww.com/v2/ > optimized_image.jpg

Rotate (auto) – /rotate/

First, an explanation of the purpose of this endpoint. Many devices still make use of the EXIF Orientation flag to indicate the direction the camera was held during the photo. This is all well and good if one never intends to edit a photo or resize it. If you strip the metadata, or create a resized version with WordPress, the Orientation flag becomes useless and your image goes sideways. So, rotation is intended to be used so that an original upload can be rotated before being used to create derivative images. The auto-rotated image is lossless, but is not optimized so that requests to this endpoint are as fast as possible. Metadata will be preserved as much as is possible, and the Orientation flag will be set to 1. The JPG format suffers from one constraint during lossless rotation, such that any image which is not evenly divisible by 16 will have up to 15 pixels trimmed from one edge during rotation. Any image sent to the standard optimization endpoint (above) will be automatically auto-rotated also. So, on to the good stuff…

Similar to optimization, there are only two required pieces of information to auto-rotate an image: api_key and a file to auto-rotate. As always, this information must be sent in a POST request. Calls to the rotation endpoint are similar to WebP generation. No credits are used, but a valid and active API key is required. The API returns the auto-rotated image directly as the response body, or a JSON-encoded error like so: {“error”:”failed”}

An error message of “failed” means that auto-rotation was not necessary, the Orientation field was absent, or something else prevented the image from being rotated. A message of “exceeded” means the API key provided was invalid. These requests should be sent to https://optimize.exactlywww.com/rotate/

The basic example with curl, assuming there is a file named ‘image_to_optimize.jpg’ in the current directory, would be as follows:

curl --form api_key=abc123 --form file=@image_to_rotate.jpg https://optimize.exactlywww.com/rotate/ > rotated_image.jpg

The file type of the optimized file should be checked to ensure that an image was returned before replacing the original image with the rotated one, since a JSON response is used to indicate no rotation was performed.

Have an idea, or need help?

If you have any questions, suggestions, or ideas about the API, feel free to contact us.