curl --request GET \
--url https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions \
--header 'X-API-Key: <api-key>'import requests
url = "https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions', 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/in-store-offers/{offer_id}/promotions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"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"
"net/http"
"io"
)
func main() {
url := "https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body[
{
"description": "Black Friday weekend",
"end_date": "2026-12-31T23:59:59Z",
"id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"is_active": true,
"metadata": {
"campaign_id": "bf-2026"
},
"offer_id": "c4d5e6f7-8901-2345-abcd-ef6789012345",
"promotion_type": "SEASONAL",
"promotional_price": {
"amount": "9.99",
"currency": "USD"
},
"short_id": "keATfB8VP2gSjcnTbsMNQL",
"start_date": "2026-11-25T00:00:00Z"
}
]{
"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"
}List in-store offer promotions
Return every promotion (active and inactive) attached to the given in-store offer. Returns 404 when the offer does not exist or the caller lacks the VIEW permission on the offer’s owning organization. 404 is used (rather than 403) to avoid leaking offer existence.
curl --request GET \
--url https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions \
--header 'X-API-Key: <api-key>'import requests
url = "https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions', 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/in-store-offers/{offer_id}/promotions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"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"
"net/http"
"io"
)
func main() {
url := "https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/retailers/api/v1/in-store-offers/{offer_id}/promotions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body[
{
"description": "Black Friday weekend",
"end_date": "2026-12-31T23:59:59Z",
"id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"is_active": true,
"metadata": {
"campaign_id": "bf-2026"
},
"offer_id": "c4d5e6f7-8901-2345-abcd-ef6789012345",
"promotion_type": "SEASONAL",
"promotional_price": {
"amount": "9.99",
"currency": "USD"
},
"short_id": "keATfB8VP2gSjcnTbsMNQL",
"start_date": "2026-11-25T00:00:00Z"
}
]{
"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 in-store offer whose promotions to list.
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$Response
OK
Stable UUID primary key of the promotion. Use this for cross-references.
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$URL-safe shortuuid (base57) encoding of id. Up to 22 characters; preferred over id in human-shareable URLs and log lines.
22UUID of the parent InStoreOffer this promotion applies to. The offer must already exist; create it via the in-store offers API before attaching promotions. Immutable after creation — moving a promotion to a different offer means deleting and recreating.
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$Timestamp at which this promotion becomes effective (inclusive). Must be strictly before end_date — the database enforces end_date > start_date.
Timestamp at which this promotion stops being effective (inclusive). A daily Celery beat task flips is_active to false once this passes; the row is kept for historical pricing rather than deleted.
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
Time-windowed override for the offer's regular price, as {"amount", "currency"} with both required together. Must be non-negative. When multiple promotions overlap on the same offer the cheapest active one wins; $0 is allowed and intentional for free-with-purchase BOGO arms (it is not a sentinel for 'unknown').
Show child attributes
Show child attributes
{ "amount": "5.99", "currency": "USD" }
Merchandising context — display-only, does not change resolution semantics. Use SEASONAL for time-of-year promotions (Black Friday, holiday), CLEARANCE for end-of-life inventory, BOGO for buy-one-get-one arms (often at promotional_price=0), BUNDLE for discounts that apply when buying with another product, INTRODUCTORY for launch pricing, LOYALTY for member-only prices, and SALE (the default) for everything else.
SALE, CLEARANCE, BOGO, BUNDLE, SEASONAL, INTRODUCTORY, LOYALTY Optional human-readable label shown alongside the promoted price (e.g. 'Black Friday weekend', 'Member appreciation week'). Free-form, up to 255 characters. Empty string when no label is needed.
255Soft-deactivate flag. true means the promotion is eligible for cheapest-active resolution within its date window; false excludes it (the daily beat task auto-flips this to false once end_date passes). Use the update endpoint to set this to false rather than deleting if you want to preserve the historical pricing row.