Images

Check an image with POST /v1/image, sent as bytes or as a public URL.

POST /v1/image checks one image and answers with the decision. One image is one check, whatever the number of categories it is checked against.

Request

PartWhereDescription
The imageBodyThe raw bytes. JPEG, PNG, WebP or GIF (the first frame). The API recognises the format from the bytes.
workflowQueryThe workflow to check against. default when absent.
refQueryYour own id for the image, 1 to 128 characters, no control character. It is echoed in the answer and kept in the journal.
urlQueryThe address of the image, instead of a body. See below.

Limits: at most 15 MB, 50 megapixels (12 on the free plan) and 16,384 pixels on a side.

curl -X POST "https://api.openshield.dev/v1/image?workflow=default&ref=avatar_4821" \
  -H "Authorization: Bearer $OPENMOD_API_KEY" \
  --data-binary @photo.jpg

Checking a public URL

Instead of sending the bytes, pass the address of the image and an empty body. The service downloads it from the public internet:

curl -X POST "https://api.openshield.dev/v1/image?url=https%3A%2F%2Fexample.com%2Fphoto.jpg" \
  -H "Authorization: Bearer $OPENMOD_API_KEY"

The download is guarded: only http and https addresses of the public internet, at most 15 MB, 3 redirects and 10 seconds, and the answer must have Content-Type: image/*. A refused address gets 400 url_refused, with the reason in message.

What is checked

The categories of the workflow. The default workflow checks nudity, gore, weapons, hate symbols and self-harm (rejected at 0.8, sent to review at 0.5), drugs and minors (sent to review at 0.5), and the text and QR codes found in the image: links to adult, unsafe or gambling sites, and extremist text. Workflows explains how to change that.

Answer

The answer has the shape described here. For an image rejected for nudity:

{
  "status": "success",
  "workflow": "default",
  "workflow_version": 1,
  "summary": {
    "action": "reject",
    "reject_prob": 0.97,
    "reject_reason": [
      {
        "id": "nudity",
        "text": "Nudity",
        "message": "This content contains nudity or sexual content.",
        "score": 0.97,
        "threshold": 0.8,
        "source": "marqo_nsfw+owen_safety"
      }
    ],
    "review_reason": []
  },
  "scores": { "nudity": 0.97, "gore": 0.01, "weapon": 0.02 },
  "time_ms": 212,
  "request_id": "0192b7c4-5f3a-7c1e-9a52-3d8f1e6b0a47",
  "ref": "avatar_4821"
}

Errors

Statuserror.typeWhen
400bad_requestThe body is empty and there is no url, or ref is refused.
400corrupt_mediaThe file does not decode.
400unknown_workflowThere is no workflow of that name.
400url_refusedThe url is not public, too large, too slow or not an image.
413body_too_largeThe body is over 15 MB.
413image_too_largeThe image has more than 50 megapixels (12 on the free plan), or a side over 16,384 pixels.
415unsupported_mediaThe file is not JPEG, PNG, WebP or GIF.
503workflow_unavailableThe workflow has no rule for images, or none this server can check.

Authentication, rate limit and quota errors are in responses and errors.

Downscale large photos to about 1,280 pixels on the longer side before sending them: the upload is smaller and faster. Keep the full size of screenshots, where small text or a QR code matters.