Reference

Smart crop

POST /v1/smartcrop — subject-aware crop to an exact width and height.

A proportional resize fits an image inside a box. Smart crop instead produces an exact width x height output by analyzing the image and cropping around whatever's most visually important, instead of just cutting from the center.

Request

POST /v1/smartcrop
POST /v1/smartcrop?async=true

multipart/form-data, same shape as /v1/optimize: an image field, and a data field whose resize.width and resize.height are required.

Terminal
curl -X POST https://api.helloimg.io/v1/smartcrop \
  -H "Authorization: Bearer <your API key>" \
  -F "[email protected]" \
  -F 'data={"resize":{"width":800,"height":800}}'

resize.smartcrop is set to true for you — you don't need to send it. Any other optimize option (level, convert, keep_exif, lossless) can be included in the same data object.

Response

Same as /v1/optimize: a 202 with a job to poll by default, or the result directly if you're not using ?async=true and the request finishes before the timeout.

Errors

StatusBodyCause
400{ "error": { "code": "invalid_request", "message": "Missing 'image' field" } }No image file in the request.
400{ "error": { "code": "invalid_request", "message": "smartcrop requires resize.width and resize.height (positive integers)" } }resize.width or resize.height is missing, zero, negative, or not an integer.
400{ "error": "resize.smartcrop cannot be combined with resize.percent: a smart crop is an exact width x height, not a proportion", "code": "invalid_resize" }Both width/height and percent were sent. Note the different, flat shape — see the callout below.
401{ "error": "invalid api key" }Missing or malformed Authorization header. Applies to every /v1/* route — one shared check in front of all of them.
429{ "error": "monthly image limit reached", "code": "limit_reached" }Free plan, 1,000 images already processed this calendar month — see Plans & limits.
Without both dimensions, smart crop would otherwise fall back silently to a proportional resize instead of a crop — so this call rejects the request outright rather than returning an image that was never actually cropped.
The two 400s above with nested error.message bodies are this endpoint's own pre-checks. Every other error on this page — auth, the plan-gate 429, and the percent-conflict case above — uses the flat { "error": "...", "code": "..." } shape instead, the same as /v1/optimize. Don't assume every error from /v1/smartcrop is nested.