curl --request POST \
--url https://www.closient.com/scanner/api/v1/captures/{short_id}/save-redirect \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"resolved_url": "https://www.brand.example/products/widget"
}
'import requests
url = "https://www.closient.com/scanner/api/v1/captures/{short_id}/save-redirect"
payload = { "resolved_url": "https://www.brand.example/products/widget" }
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({resolved_url: 'https://www.brand.example/products/widget'})
};
fetch('https://www.closient.com/scanner/api/v1/captures/{short_id}/save-redirect', 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/captures/{short_id}/save-redirect",
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([
'resolved_url' => 'https://www.brand.example/products/widget'
]),
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/captures/{short_id}/save-redirect"
payload := strings.NewReader("{\n \"resolved_url\": \"https://www.brand.example/products/widget\"\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/captures/{short_id}/save-redirect")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"resolved_url\": \"https://www.brand.example/products/widget\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/scanner/api/v1/captures/{short_id}/save-redirect")
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 \"resolved_url\": \"https://www.brand.example/products/widget\"\n}"
response = http.request(request)
puts response.read_body{
"custom_url": "https://www.brand.example/products/widget",
"order_index": 3,
"product_short_id": "trail-mix-12oz",
"rule_short_id": "rule-a1b2c3"
}{
"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"
}{
"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"
}Save a QR-resolved URL as a trade-item redirect
Persist a URL — typically the final_url from /resolve-url — as a PRODUCT-scoped resolution rule on the trade item linked to this capture.
Returns 400 when the capture has no linked product (the lookup pipeline either has not run yet or did not match). The client should retry once capture_status is COMPLETED.
The rule is written into the organization that owns the product, so the product must be one your organization owns: another organization’s product returns 404 (the status never confirms who claimed a GTIN), a credential whose role cannot contribute returns 403, and an unclaimed product returns 409 — claim it first.
The new rule is appended to the end of the product’s existing rule list so it never silently jumps ahead of a manually-curated rule. Manage / reorder via the resolver UI.
curl --request POST \
--url https://www.closient.com/scanner/api/v1/captures/{short_id}/save-redirect \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"resolved_url": "https://www.brand.example/products/widget"
}
'import requests
url = "https://www.closient.com/scanner/api/v1/captures/{short_id}/save-redirect"
payload = { "resolved_url": "https://www.brand.example/products/widget" }
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({resolved_url: 'https://www.brand.example/products/widget'})
};
fetch('https://www.closient.com/scanner/api/v1/captures/{short_id}/save-redirect', 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/captures/{short_id}/save-redirect",
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([
'resolved_url' => 'https://www.brand.example/products/widget'
]),
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/captures/{short_id}/save-redirect"
payload := strings.NewReader("{\n \"resolved_url\": \"https://www.brand.example/products/widget\"\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/captures/{short_id}/save-redirect")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"resolved_url\": \"https://www.brand.example/products/widget\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/scanner/api/v1/captures/{short_id}/save-redirect")
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 \"resolved_url\": \"https://www.brand.example/products/widget\"\n}"
response = http.request(request)
puts response.read_body{
"custom_url": "https://www.brand.example/products/widget",
"order_index": 3,
"product_short_id": "trail-mix-12oz",
"rule_short_id": "rule-a1b2c3"
}{
"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"
}{
"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 capture short_id identifier.
Body
Request body for accepting a resolved URL as a trade-item redirect.
URL to persist as the redirect destination. Stored as-is — no further transformation, no tracking-param stripping in v1. Typically the final_url returned by /resolve-url.
1 - 2048Response
Created
Result of saving a resolved URL as a PRODUCT-scoped resolution rule.
Short ID of the new resolution rule.
Short ID of the linked trade item.
Persisted custom URL on the rule.
Evaluation index assigned to the new rule within the PRODUCT scope. Appended to the end of any existing list.
x >= 0