curl --request POST \
--url https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"capture_short_id": "cap-a1b2c3",
"file_size": 245760,
"metadata": {
"order_id": "6735"
},
"original_filename": "IMG_1234.jpg",
"photo_type": "front",
"s3_key": "scans/2025/08/photo-x1y2z3.jpg"
}
'import requests
url = "https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos"
payload = {
"capture_short_id": "cap-a1b2c3",
"file_size": 245760,
"metadata": { "order_id": "6735" },
"original_filename": "IMG_1234.jpg",
"photo_type": "front",
"s3_key": "scans/2025/08/photo-x1y2z3.jpg"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
capture_short_id: 'cap-a1b2c3',
file_size: 245760,
metadata: {order_id: '6735'},
original_filename: 'IMG_1234.jpg',
photo_type: 'front',
s3_key: 'scans/2025/08/photo-x1y2z3.jpg'
})
};
fetch('https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'capture_short_id' => 'cap-a1b2c3',
'file_size' => 245760,
'metadata' => [
'order_id' => '6735'
],
'original_filename' => 'IMG_1234.jpg',
'photo_type' => 'front',
's3_key' => 'scans/2025/08/photo-x1y2z3.jpg'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos"
payload := strings.NewReader("{\n \"capture_short_id\": \"cap-a1b2c3\",\n \"file_size\": 245760,\n \"metadata\": {\n \"order_id\": \"6735\"\n },\n \"original_filename\": \"IMG_1234.jpg\",\n \"photo_type\": \"front\",\n \"s3_key\": \"scans/2025/08/photo-x1y2z3.jpg\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"capture_short_id\": \"cap-a1b2c3\",\n \"file_size\": 245760,\n \"metadata\": {\n \"order_id\": \"6735\"\n },\n \"original_filename\": \"IMG_1234.jpg\",\n \"photo_type\": \"front\",\n \"s3_key\": \"scans/2025/08/photo-x1y2z3.jpg\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"capture_short_id\": \"cap-a1b2c3\",\n \"file_size\": 245760,\n \"metadata\": {\n \"order_id\": \"6735\"\n },\n \"original_filename\": \"IMG_1234.jpg\",\n \"photo_type\": \"front\",\n \"s3_key\": \"scans/2025/08/photo-x1y2z3.jpg\"\n}"
response = http.request(request)
puts response.read_body{
"capture_short_id": "cap-a1b2c3",
"created": "2025-08-15T14:30:00Z",
"file_size": 245760,
"metadata": {
"order_id": "6735"
},
"original_filename": "IMG_1234.jpg",
"photo_type": "front",
"s3_key": "scans/2025/08/photo-x1y2z3.jpg",
"sort_order": 1
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}Register a product photo
Register a product photo after it has been uploaded to S3.
curl --request POST \
--url https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"capture_short_id": "cap-a1b2c3",
"file_size": 245760,
"metadata": {
"order_id": "6735"
},
"original_filename": "IMG_1234.jpg",
"photo_type": "front",
"s3_key": "scans/2025/08/photo-x1y2z3.jpg"
}
'import requests
url = "https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos"
payload = {
"capture_short_id": "cap-a1b2c3",
"file_size": 245760,
"metadata": { "order_id": "6735" },
"original_filename": "IMG_1234.jpg",
"photo_type": "front",
"s3_key": "scans/2025/08/photo-x1y2z3.jpg"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
capture_short_id: 'cap-a1b2c3',
file_size: 245760,
metadata: {order_id: '6735'},
original_filename: 'IMG_1234.jpg',
photo_type: 'front',
s3_key: 'scans/2025/08/photo-x1y2z3.jpg'
})
};
fetch('https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'capture_short_id' => 'cap-a1b2c3',
'file_size' => 245760,
'metadata' => [
'order_id' => '6735'
],
'original_filename' => 'IMG_1234.jpg',
'photo_type' => 'front',
's3_key' => 'scans/2025/08/photo-x1y2z3.jpg'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos"
payload := strings.NewReader("{\n \"capture_short_id\": \"cap-a1b2c3\",\n \"file_size\": 245760,\n \"metadata\": {\n \"order_id\": \"6735\"\n },\n \"original_filename\": \"IMG_1234.jpg\",\n \"photo_type\": \"front\",\n \"s3_key\": \"scans/2025/08/photo-x1y2z3.jpg\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"capture_short_id\": \"cap-a1b2c3\",\n \"file_size\": 245760,\n \"metadata\": {\n \"order_id\": \"6735\"\n },\n \"original_filename\": \"IMG_1234.jpg\",\n \"photo_type\": \"front\",\n \"s3_key\": \"scans/2025/08/photo-x1y2z3.jpg\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/scanner/api/v1/sessions/{session_id}/photos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"capture_short_id\": \"cap-a1b2c3\",\n \"file_size\": 245760,\n \"metadata\": {\n \"order_id\": \"6735\"\n },\n \"original_filename\": \"IMG_1234.jpg\",\n \"photo_type\": \"front\",\n \"s3_key\": \"scans/2025/08/photo-x1y2z3.jpg\"\n}"
response = http.request(request)
puts response.read_body{
"capture_short_id": "cap-a1b2c3",
"created": "2025-08-15T14:30:00Z",
"file_size": 245760,
"metadata": {
"order_id": "6735"
},
"original_filename": "IMG_1234.jpg",
"photo_type": "front",
"s3_key": "scans/2025/08/photo-x1y2z3.jpg",
"sort_order": 1
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}Authorizations
Path Parameters
Unique session short_id identifier.
Body
Request body for registering a product photo.
S3 object key returned by the presigned upload.
Developer-attached key/value data. Send {} or null to clear. Empty-string values delete that key. Omitted keys are preserved.
Show child attributes
Show child attributes
Classification label — which side or aspect of the product this photo shows. Drives routing through the vision pipeline (e.g. nutrition photos go to the nutrition-facts extractor). Defaults to other when the operator does not assign a label.
front, back, left, right, top, bottom, nutrition, ingredients, barcode, recycling, certification, other Slug of the barcode capture to link this photo to.
Original filename as provided by the client.
File size in bytes.
Response
Created
A single product photo in a scan session gallery.
Classification label — which side or aspect of the product this photo shows. Drives routing through the vision pipeline (e.g. nutrition photos go to the nutrition-facts extractor).
front, back, left, right, top, bottom, nutrition, ingredients, barcode, recycling, certification, other S3 object key for the photo file.
Original filename.
Display position.
Timestamp when the photo was registered.
Developer-attached key/value data attached to this object. Up to 50 keys; key max 40 chars, value max 500 chars.
Show child attributes
Show child attributes
File size in bytes.
Slug of the linked barcode capture.