curl --request POST \
--url https://www.closient.com/products/api/v1/labels/export/ \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"export_type": "datamatrix",
"file_format": "svg",
"filters": {
"gtins": [
"00012345678905"
],
"never_printed": true
},
"scope": "lots"
}
'import requests
url = "https://www.closient.com/products/api/v1/labels/export/"
payload = {
"export_type": "datamatrix",
"file_format": "svg",
"filters": {
"gtins": ["00012345678905"],
"never_printed": True
},
"scope": "lots"
}
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({
export_type: 'datamatrix',
file_format: 'svg',
filters: {gtins: ['00012345678905'], never_printed: true},
scope: 'lots'
})
};
fetch('https://www.closient.com/products/api/v1/labels/export/', 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/products/api/v1/labels/export/",
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([
'export_type' => 'datamatrix',
'file_format' => 'svg',
'filters' => [
'gtins' => [
'00012345678905'
],
'never_printed' => true
],
'scope' => 'lots'
]),
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/products/api/v1/labels/export/"
payload := strings.NewReader("{\n \"export_type\": \"datamatrix\",\n \"file_format\": \"svg\",\n \"filters\": {\n \"gtins\": [\n \"00012345678905\"\n ],\n \"never_printed\": true\n },\n \"scope\": \"lots\"\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/products/api/v1/labels/export/")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"export_type\": \"datamatrix\",\n \"file_format\": \"svg\",\n \"filters\": {\n \"gtins\": [\n \"00012345678905\"\n ],\n \"never_printed\": true\n },\n \"scope\": \"lots\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/products/api/v1/labels/export/")
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 \"export_type\": \"datamatrix\",\n \"file_format\": \"svg\",\n \"filters\": {\n \"gtins\": [\n \"00012345678905\"\n ],\n \"never_printed\": true\n },\n \"scope\": \"lots\"\n}"
response = http.request(request)
puts response.read_body{
"job_id": "AbCdEfGhIjKlMnOpQrStUv",
"poll_url": "/products/api/v1/labels/export/AbCdEfGhIjKlMnOpQrStUv/",
"status": "pending"
}{
"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"
}Submit a bulk label-export job
Queue a bulk label-export job and return the job id. Polling endpoint (GET /labels/export/{job_id}/) returns status and a temporary signed download URL once complete. Small jobs run synchronously inside the request — the very first poll will already report completed. Larger jobs queue for background processing and progress through processing → completed.
curl --request POST \
--url https://www.closient.com/products/api/v1/labels/export/ \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"export_type": "datamatrix",
"file_format": "svg",
"filters": {
"gtins": [
"00012345678905"
],
"never_printed": true
},
"scope": "lots"
}
'import requests
url = "https://www.closient.com/products/api/v1/labels/export/"
payload = {
"export_type": "datamatrix",
"file_format": "svg",
"filters": {
"gtins": ["00012345678905"],
"never_printed": True
},
"scope": "lots"
}
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({
export_type: 'datamatrix',
file_format: 'svg',
filters: {gtins: ['00012345678905'], never_printed: true},
scope: 'lots'
})
};
fetch('https://www.closient.com/products/api/v1/labels/export/', 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/products/api/v1/labels/export/",
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([
'export_type' => 'datamatrix',
'file_format' => 'svg',
'filters' => [
'gtins' => [
'00012345678905'
],
'never_printed' => true
],
'scope' => 'lots'
]),
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/products/api/v1/labels/export/"
payload := strings.NewReader("{\n \"export_type\": \"datamatrix\",\n \"file_format\": \"svg\",\n \"filters\": {\n \"gtins\": [\n \"00012345678905\"\n ],\n \"never_printed\": true\n },\n \"scope\": \"lots\"\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/products/api/v1/labels/export/")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"export_type\": \"datamatrix\",\n \"file_format\": \"svg\",\n \"filters\": {\n \"gtins\": [\n \"00012345678905\"\n ],\n \"never_printed\": true\n },\n \"scope\": \"lots\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/products/api/v1/labels/export/")
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 \"export_type\": \"datamatrix\",\n \"file_format\": \"svg\",\n \"filters\": {\n \"gtins\": [\n \"00012345678905\"\n ],\n \"never_printed\": true\n },\n \"scope\": \"lots\"\n}"
response = http.request(request)
puts response.read_body{
"job_id": "AbCdEfGhIjKlMnOpQrStUv",
"poll_url": "/products/api/v1/labels/export/AbCdEfGhIjKlMnOpQrStUv/",
"status": "pending"
}{
"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
Body
Request body for POST /products/api/v1/labels/export/.
Mirrors the field set the Dashboard's bulk-export form posts. The
combination (export_type, file_format) must be coherent — sheet
PDFs require file_format='pdf'; the symbology ZIP exports
(qr_codes / datamatrix) accept svg/png; barcodes_1d
accepts svg/eps.
Which entity table the filters resolve against. lots and serials are supported today; products is reserved for a future per-product export and currently rejected at the renderer layer.
products, lots, serials What asset the job produces. qr_codes / datamatrix / barcodes_1d produce ZIPs of one symbol per entity; sheet_pdf produces a multi-up label sheet PDF; codes_combined produces ZIPs containing both QR and 1D variants per entity.
qr_codes, datamatrix, barcodes_1d, codes_combined, sheet_pdf Output container/format. Must be coherent with export_type: sheet_pdf requires pdf; qr_codes/datamatrix accept svg/png; barcodes_1d accepts svg/eps.
svg, png, pdf, eps Optional selection filters. Omit to export every active lot/serial in the caller's organization at the chosen scope. Use a narrowing key (gtins, product_id, lot_ids/serial_ids, lot_run_id, etc.) to bound the result set.
Show child attributes
Show child attributes
{
"gtins": ["00012345678905"],
"never_printed": true
}
Optional renderer-side knobs for sheet_pdf (sheet template, copies, grid). Defaults apply when omitted.
Show child attributes
Show child attributes
{
"copies": 2,
"grid": false,
"sheet_template": "avery:5160"
}
Response
Accepted
Response for an accepted bulk-label-export job — always HTTP 202.
Even when the underlying job runs synchronously (a small job), the response shape is the receipt-only envelope: callers always poll the status endpoint to fetch the download URL. This keeps the API contract identical regardless of which side of the cutover the job lands on.
Identifier of the queued LabelExportJob (22-char shortuuid). Use to poll the status endpoint at GET /labels/export/{job_id}/.
Initial lifecycle state at submission. Typically pending; for very small jobs that ran inline this may already be completed or failed.
pending, processing, completed, failed Relative URL of the polling endpoint for this job — combine with the API host to retrieve status. Embeds the same job_id for convenience.