curl --request PUT \
--url https://www.closient.com/retailers/api/v1/online-offers/{offer_id} \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"price": {
"amount": "6.49",
"currency": "USD"
},
"sku": "AMZ-TM-12OZ-V2",
"status": "active",
"stock_level": "low_stock",
"url": "https://www.amazon.com/dp/B001235"
}
'import requests
url = "https://www.closient.com/retailers/api/v1/online-offers/{offer_id}"
payload = {
"price": {
"amount": "6.49",
"currency": "USD"
},
"sku": "AMZ-TM-12OZ-V2",
"status": "active",
"stock_level": "low_stock",
"url": "https://www.amazon.com/dp/B001235"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
price: {amount: '6.49', currency: 'USD'},
sku: 'AMZ-TM-12OZ-V2',
status: 'active',
stock_level: 'low_stock',
url: 'https://www.amazon.com/dp/B001235'
})
};
fetch('https://www.closient.com/retailers/api/v1/online-offers/{offer_id}', 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/retailers/api/v1/online-offers/{offer_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'price' => [
'amount' => '6.49',
'currency' => 'USD'
],
'sku' => 'AMZ-TM-12OZ-V2',
'status' => 'active',
'stock_level' => 'low_stock',
'url' => 'https://www.amazon.com/dp/B001235'
]),
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/retailers/api/v1/online-offers/{offer_id}"
payload := strings.NewReader("{\n \"price\": {\n \"amount\": \"6.49\",\n \"currency\": \"USD\"\n },\n \"sku\": \"AMZ-TM-12OZ-V2\",\n \"status\": \"active\",\n \"stock_level\": \"low_stock\",\n \"url\": \"https://www.amazon.com/dp/B001235\"\n}")
req, _ := http.NewRequest("PUT", 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.put("https://www.closient.com/retailers/api/v1/online-offers/{offer_id}")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"price\": {\n \"amount\": \"6.49\",\n \"currency\": \"USD\"\n },\n \"sku\": \"AMZ-TM-12OZ-V2\",\n \"status\": \"active\",\n \"stock_level\": \"low_stock\",\n \"url\": \"https://www.amazon.com/dp/B001235\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/retailers/api/v1/online-offers/{offer_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"price\": {\n \"amount\": \"6.49\",\n \"currency\": \"USD\"\n },\n \"sku\": \"AMZ-TM-12OZ-V2\",\n \"status\": \"active\",\n \"stock_level\": \"low_stock\",\n \"url\": \"https://www.amazon.com/dp/B001235\"\n}"
response = http.request(request)
puts response.read_body{
"delivery_countries": [
"US",
"CA"
],
"fulfillment_type": "prime",
"id": "d5e6f7a8-9012-3456-abcd-ef7890123456",
"is_verified": false,
"lead_time_days": 2,
"metadata": {
"feed_id": "amzn-2026-q2"
},
"min_order_quantity": 1,
"online_store_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"organization_id": "9b2c3d4e-f5a6-7890-abcd-ef1234567890",
"price": {
"amount": "5.99",
"currency": "USD"
},
"product_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"shipping_cost": {
"amount": "0.00",
"currency": "USD"
},
"sku": "AMZ-TM-12OZ",
"source": "affiliate_feed",
"status": "active",
"stock_level": "in_stock",
"url": "https://www.amazon.com/dp/B001234"
}{
"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"
}Update online offer
Partially update an online offer. Omitted keys preserve existing values; metadata follows Stripe semantics (empty string deletes a key, null clears all). Returns 404 when the offer does not exist or the caller lacks MANAGE_OFFERS on the offer’s owning organization.
curl --request PUT \
--url https://www.closient.com/retailers/api/v1/online-offers/{offer_id} \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"price": {
"amount": "6.49",
"currency": "USD"
},
"sku": "AMZ-TM-12OZ-V2",
"status": "active",
"stock_level": "low_stock",
"url": "https://www.amazon.com/dp/B001235"
}
'import requests
url = "https://www.closient.com/retailers/api/v1/online-offers/{offer_id}"
payload = {
"price": {
"amount": "6.49",
"currency": "USD"
},
"sku": "AMZ-TM-12OZ-V2",
"status": "active",
"stock_level": "low_stock",
"url": "https://www.amazon.com/dp/B001235"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
price: {amount: '6.49', currency: 'USD'},
sku: 'AMZ-TM-12OZ-V2',
status: 'active',
stock_level: 'low_stock',
url: 'https://www.amazon.com/dp/B001235'
})
};
fetch('https://www.closient.com/retailers/api/v1/online-offers/{offer_id}', 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/retailers/api/v1/online-offers/{offer_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'price' => [
'amount' => '6.49',
'currency' => 'USD'
],
'sku' => 'AMZ-TM-12OZ-V2',
'status' => 'active',
'stock_level' => 'low_stock',
'url' => 'https://www.amazon.com/dp/B001235'
]),
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/retailers/api/v1/online-offers/{offer_id}"
payload := strings.NewReader("{\n \"price\": {\n \"amount\": \"6.49\",\n \"currency\": \"USD\"\n },\n \"sku\": \"AMZ-TM-12OZ-V2\",\n \"status\": \"active\",\n \"stock_level\": \"low_stock\",\n \"url\": \"https://www.amazon.com/dp/B001235\"\n}")
req, _ := http.NewRequest("PUT", 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.put("https://www.closient.com/retailers/api/v1/online-offers/{offer_id}")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"price\": {\n \"amount\": \"6.49\",\n \"currency\": \"USD\"\n },\n \"sku\": \"AMZ-TM-12OZ-V2\",\n \"status\": \"active\",\n \"stock_level\": \"low_stock\",\n \"url\": \"https://www.amazon.com/dp/B001235\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/retailers/api/v1/online-offers/{offer_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"price\": {\n \"amount\": \"6.49\",\n \"currency\": \"USD\"\n },\n \"sku\": \"AMZ-TM-12OZ-V2\",\n \"status\": \"active\",\n \"stock_level\": \"low_stock\",\n \"url\": \"https://www.amazon.com/dp/B001235\"\n}"
response = http.request(request)
puts response.read_body{
"delivery_countries": [
"US",
"CA"
],
"fulfillment_type": "prime",
"id": "d5e6f7a8-9012-3456-abcd-ef7890123456",
"is_verified": false,
"lead_time_days": 2,
"metadata": {
"feed_id": "amzn-2026-q2"
},
"min_order_quantity": 1,
"online_store_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"organization_id": "9b2c3d4e-f5a6-7890-abcd-ef1234567890",
"price": {
"amount": "5.99",
"currency": "USD"
},
"product_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"shipping_cost": {
"amount": "0.00",
"currency": "USD"
},
"sku": "AMZ-TM-12OZ",
"source": "affiliate_feed",
"status": "active",
"stock_level": "in_stock",
"url": "https://www.amazon.com/dp/B001234"
}{
"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
UUID of the online offer to update.
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$Body
Partial update payload for an online offer.
Every field is optional. Omitted keys preserve existing values (PATCH semantics on a
PUT endpoint, kept for backward compatibility). product_id and online_store_id
are not updatable — delete and recreate to move a row.
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
Storefront-specific SKU (or ASIN, item ID, etc.) for this product on this site. Empty string when the source doesn't expose one. Together with product_id and online_store_id this is the row's natural key — the trio must be unique.
100Deep link to the product page on the storefront. Should resolve to a buyable page; url_status reflects the most recent reachability check. Empty string when the source did not expose a URL (rare for online offers — usually means a feed-only row without a public PDP yet).
1000Price as {"amount", "currency"}; both are required together. Omit or send null when the price is unknown; the row is then priceless and excluded from cheapest-active resolution. There is no default currency — an amount alone is rejected.
Show child attributes
Show child attributes
{ "amount": "5.99", "currency": "USD" }
Lifecycle state of this offer on the storefront. active is resolvable; out_of_stock, seasonal, and discontinued are filtered out of cheapest-active resolution. status is independent of stock_level — an offer can be active with stock_level=low_stock.
active, discontinued, seasonal, out_of_stock Where this offer row came from. Affects source_priority defaults used when reconciling conflicting rows for the same (product, store, sku). manual is the safe default for ad-hoc API writes; affiliate_feed for partner-feed ingest.
brand, affiliate_feed, scrape, pos_sync, manual, user_feedback How the storefront delivers this offer to the buyer. standard is plain ground shipping; prime covers Amazon Prime / equivalent fast-shipping memberships; ship_to_store and store_pickup involve a brick-and-mortar leg even though the offer is online. Only meaningful for offers where url is buyable.
standard, same_day, next_day, prime, ship_to_store, store_pickup, digital_download, subscribe_and_save How much inventory is reported by the storefront. in_stock and low_stock are buyable now; pre_order and backordered are buyable but with a wait; out_of_stock is unbuyable; unknown is the safe default when the source doesn't surface stock signals.
in_stock, low_stock, pre_order, backordered, out_of_stock, unknown ISO 3166-1 alpha-2 country codes this offer ships to (e.g. ["US"], ["US", "CA"]). Empty list means inherit from storefront — the API does not infer a default. Codes must be uppercase 2-letter.
Shipping cost as {"amount", "currency"}, both required together. null when free or unknown — distinguish via fulfillment_type (prime and similar imply free) or by the storefront's documented behaviour.
Show child attributes
Show child attributes
{ "amount": "5.99", "currency": "USD" }
Expected handling + shipping time in calendar days. null when unknown. Same-day and next-day fulfillment types ought to report 0 or 1; backordered offers may report higher values reflecting restock ETAs.
x >= 0Minimum number of units that must be purchased in a single order. Defaults to 1. Higher values are common for wholesale/B2B feeds.
x >= 1Response
OK
An offer for a product on a specific online storefront.
Mirrors :class:apps.retailers.models.OnlineOffer, whose price and
shipping_cost each store their amount and currency together. One row per
(product, online_store, sku) — that trio is the unique key.
URL-safe 22-character shortuuid encoding of the row's UUID primary key. Stable across the row's lifetime; suitable for sharing in URLs, log lines, and external SDK clients. Accepted on input as either the shortuuid form or the canonical UUID form (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$UUID of the catalog Product this offer is for. The product must already exist; create it via the products API before adding offers. Immutable after creation — moving a row to a different product means deleting and recreating.
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$UUID of the OnlineStore (a single web storefront — amazon.com, wholefoodsmarket.com, etc., not the parent retailer entity) this offer lives on. The currency on the parent store is what price and shipping_cost are denominated in — there is no per-offer currency override.
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$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
URL-safe 22-character shortuuid encoding of the row's UUID primary key. Stable across the row's lifetime; suitable for sharing in URLs, log lines, and external SDK clients. Accepted on input as either the shortuuid form or the canonical UUID form (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$Storefront-specific SKU (or ASIN, item ID, etc.) for this product on this site. Empty string when the source doesn't expose one. Together with product_id and online_store_id this is the row's natural key — the trio must be unique.
100Deep link to the product page on the storefront. Should resolve to a buyable page; url_status reflects the most recent reachability check. Empty string when the source did not expose a URL (rare for online offers — usually means a feed-only row without a public PDP yet).
1000Structured price: amount and currency are stored together on the row and returned together. Both are null when the price is unknown — never assume a denomination for a null.
Show child attributes
Show child attributes
{ "amount": "5.99", "currency": "USD" }
Lifecycle state of this offer on the storefront. active is resolvable; out_of_stock, seasonal, and discontinued are filtered out of cheapest-active resolution. status is independent of stock_level — an offer can be active with stock_level=low_stock.
active, discontinued, seasonal, out_of_stock true when Closient has confirmed this offer is real. Read-only: set only by Closient-controlled paths, never through this API. An offer submitted by an organization other than the product's owner is shown on public surfaces (product page, search, structured data) only when this is true.
Where this offer row came from. Affects source_priority defaults used when reconciling conflicting rows for the same (product, store, sku). manual is the safe default for ad-hoc API writes; affiliate_feed for partner-feed ingest.
brand, affiliate_feed, scrape, pos_sync, manual, user_feedback How the storefront delivers this offer to the buyer. standard is plain ground shipping; prime covers Amazon Prime / equivalent fast-shipping memberships; ship_to_store and store_pickup involve a brick-and-mortar leg even though the offer is online. Only meaningful for offers where url is buyable.
standard, same_day, next_day, prime, ship_to_store, store_pickup, digital_download, subscribe_and_save How much inventory is reported by the storefront. in_stock and low_stock are buyable now; pre_order and backordered are buyable but with a wait; out_of_stock is unbuyable; unknown is the safe default when the source doesn't surface stock signals.
in_stock, low_stock, pre_order, backordered, out_of_stock, unknown ISO 3166-1 alpha-2 country codes this offer ships to (e.g. ["US"], ["US", "CA"]). Empty list means inherit from storefront — the API does not infer a default. Codes must be uppercase 2-letter.
Shipping cost as {"amount", "currency"}, both required together. null when free or unknown — distinguish via fulfillment_type (prime and similar imply free) or by the storefront's documented behaviour.
Show child attributes
Show child attributes
{ "amount": "5.99", "currency": "USD" }
Expected handling + shipping time in calendar days. null when unknown. Same-day and next-day fulfillment types ought to report 0 or 1; backordered offers may report higher values reflecting restock ETAs.
x >= 0Minimum number of units that must be purchased in a single order. Defaults to 1. Higher values are common for wholesale/B2B feeds.
x >= 1