Ninetile

Recognition API

POST https://api.ninetile.io/v1/recognize accepts one challenge and returns an answer synchronously. It does not return a token. An answered request is charged at $0.30 per 1,000 answers; a puzzle that cannot be answered returns 422 recognition_failed without a charge.

Simple grid and area-select form

  • type: hcaptcha for a grid or hcaptcha_area_select for a point challenge.
  • task: English instruction, nonempty and at most 500 characters.
  • image_data or image_urls: images in task order. Grid accepts 1–27 images; area-select accepts exactly one.
  • image_examples (optional): 1–3 reference images.

Images may be bare base64 or a base64 data URI. URLs must be HTTPS on hcaptcha.com or a subdomain; arbitrary URLs are not fetched. PNG, JPEG, GIF and WebP are supported. Each image is limited to 1.5 MiB and 1 megapixel; all images together are limited to 12 megapixels and the request to 12 MiB.

{
  "type": "hcaptcha",
  "task": "Select all bicycles",
  "image_data": ["<BASE64_IMAGE_1>", "<BASE64_IMAGE_2>"]
}

Send this JSON to https://api.ninetile.io/v1/recognize with an API key and JSON content type. The placeholders must be replaced with actual image data.

Full challenge form

Use {"data": {...}} for the full challenge object. data.request_type is one of:

  • image_label_binary: up to 27 tasks.
  • image_label_area_select: up to 5 tasks.
  • image_drag_drop: up to 5 tasks; each drag task needs an entities array.

data.requester_question.en must contain the instruction. Each data.tasklist item needs a nonempty task_key and datapoint_uri. Drag entities use entity_uri; keep the challenge's entity identifiers intact. Image restrictions also apply to these fields.

Answer shapes

For a simple grid, data is a boolean for each tile in the same order. For simple area select, data contains x, y, w: 0, and h: 0, with points listing all click positions. Coordinates are percentages of image dimensions. Drag answers contain each entity ID and its box in percentage coordinates; the drop centre is (x + w/2, y + h/2). The full challenge form returns answers grouped by task.

Responses also include an id and charged_usd. Optionally report {"id":"rec_...","result":"solved"} or "failed" to POST /v1/recognize/outcome; reporting an outcome does not change billing. Video challenges are not accepted by the HTTP Recognition API.

Illustrative responses

A simple grid response preserves input order:

{"id":"rec_example","data":[true,false],"charged_usd":0.0003}

For an area task, a response may include:

{"id":"rec_example","data":{"x":25,"y":60,"w":0,"h":0},"points":[{"x":25,"y":60}],"charged_usd":0.0003}

These IDs and coordinates are examples, not actual solutions. Full-form area responses contain one data entry and one points list per task. A full grid response groups boolean answers by page. Drag results preserve the predictor's boxes and entity identifiers. An outcome report returns id, result and refunded_usd: 0.

Full-form request structure

{"data":{"request_type":"image_label_binary","requester_question":{"en":"Select all bicycles"},"tasklist":[{"task_key":"task-1","datapoint_uri":"<BASE64_IMAGE>"}]}}

This is a structural example; replace the placeholder with real image data. For drag tasks use image_drag_drop and provide each task's entities array with entity image URIs and identifiers. Do not substitute a made-up entity ID for the challenge's ID.