Coupons
List, read, create, and update store coupons.
The coupons endpoints read and manage a store's coupons, including the coupons a given avatar owns. A coupon's owner is the avatar who receives the coupon's commission (its ownerProfit share), which is distinct from the customer who applies the coupon to get the discount. Field shapes are on the Object reference page.
List an avatar's coupons
GET /v1/coupons/owner/{identifier}Returns a cursor-paginated list of the coupons owned by one avatar, the avatar who receives each coupon's commission. Scope: coupons:read. The {identifier} is that avatar's Second Life username or UUID. Query parameters limit and cursor are optional; see Pagination and errors.
curl --fail-with-body "https://integrations.allomancy.net/v1/coupons/owner/resident.username?limit=50" \
-H "X-API-Key: allo_live_8Kd2...zQ.Hk9...4w"import requests
response = requests.get(
"https://integrations.allomancy.net/v1/coupons/owner/resident.username",
headers={"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w"},
params={"limit": 50},
)
print(response.json())const response = await fetch(
"https://integrations.allomancy.net/v1/coupons/owner/resident.username?limit=50",
{
headers: { "X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w" },
},
);
console.log(await response.json());<?php
$ch = curl_init("https://integrations.allomancy.net/v1/coupons/owner/resident.username?limit=50");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-API-Key: allo_live_8Kd2...zQ.Hk9...4w"]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Each row is a CouponResponse. Status: 200, 400, or 404 if the avatar cannot be resolved.
List all coupons
GET /v1/couponsReturns a cursor-paginated list of every coupon in the store. Scope: coupons:read.
An optional active (boolean) query parameter narrows the list to active or inactive coupons. It applies to this endpoint only; List an avatar's coupons does not take it.
curl --fail-with-body "https://integrations.allomancy.net/v1/coupons?limit=50" \
-H "X-API-Key: allo_live_8Kd2...zQ.Hk9...4w"import requests
response = requests.get(
"https://integrations.allomancy.net/v1/coupons",
headers={"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w"},
params={"limit": 50},
)
print(response.json())const response = await fetch(
"https://integrations.allomancy.net/v1/coupons?limit=50",
{
headers: { "X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w" },
},
);
console.log(await response.json());<?php
$ch = curl_init("https://integrations.allomancy.net/v1/coupons?limit=50");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-API-Key: allo_live_8Kd2...zQ.Hk9...4w"]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;{
"data": [
{
"id": "e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
"code": "WELCOME10",
"active": true,
"bloggersSync": false,
"couponOwnerUuid": "c7d8e9f0-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
"couponOwnerUsername": "resident.username",
"discount": 10,
"ownerProfit": 0,
"usesPerCustomer": 1,
"expiration": "2026-12-31T00:00:00Z"
}
],
"pagination": { "nextCursor": null, "previousCursor": null, "limit": 50 }
}Each row is a CouponResponse. Status: 200, or 400 for a bad pagination parameter.
Get a coupon
GET /v1/coupons/{id}Returns one coupon by its UUID. Scope: coupons:read.
curl --fail-with-body https://integrations.allomancy.net/v1/coupons/e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b \
-H "X-API-Key: allo_live_8Kd2...zQ.Hk9...4w"import requests
response = requests.get(
"https://integrations.allomancy.net/v1/coupons/e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
headers={"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w"},
)
print(response.json())const response = await fetch(
"https://integrations.allomancy.net/v1/coupons/e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
{
headers: { "X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w" },
},
);
console.log(await response.json());<?php
$ch = curl_init("https://integrations.allomancy.net/v1/coupons/e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-API-Key: allo_live_8Kd2...zQ.Hk9...4w"]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;The response is a CouponResponse. Status: 200, or 404 if no coupon matches.
Create a coupon
POST /v1/couponsCreates a coupon. Scope: coupons:write. The body is a CreateCouponRequest, where ownerIdentifier is the owning avatar's Second Life username or UUID.
curl --fail-with-body https://integrations.allomancy.net/v1/coupons \
-H "X-API-Key: allo_live_8Kd2...zQ.Hk9...4w" \
-H "Content-Type: application/json" \
-d '{
"code": "WELCOME10",
"discount": 10,
"ownerProfit": 0,
"ownerIdentifier": "resident.username",
"active": true,
"bloggersSync": false
}'import requests
response = requests.post(
"https://integrations.allomancy.net/v1/coupons",
headers={"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w"},
json={
"code": "WELCOME10",
"discount": 10,
"ownerProfit": 0,
"ownerIdentifier": "resident.username",
"active": True,
"bloggersSync": False,
},
)
print(response.json())const response = await fetch("https://integrations.allomancy.net/v1/coupons", {
method: "POST",
headers: {
"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w",
"Content-Type": "application/json",
},
body: JSON.stringify({
code: "WELCOME10",
discount: 10,
ownerProfit: 0,
ownerIdentifier: "resident.username",
active: true,
bloggersSync: false,
}),
});
console.log(await response.json());<?php
$ch = curl_init("https://integrations.allomancy.net/v1/coupons");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-API-Key: allo_live_8Kd2...zQ.Hk9...4w",
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
"code" => "WELCOME10",
"discount" => 10,
"ownerProfit" => 0,
"ownerIdentifier" => "resident.username",
"active" => true,
"bloggersSync" => false,
]));
$response = curl_exec($ch);
curl_close($ch);
echo $response;On success the response is 201 Created with a Location header pointing at the new coupon, and the body is the created CouponResponse. Status: 201, 400, or 404.
Update a coupon
PUT /v1/coupons/{id}Updates a coupon. Scope: coupons:write. The body is an UpdateCouponRequest, and it replaces the coupon's fields: an omitted field is set to its default rather than left at its previous value. The coupon's owner is fixed at creation and cannot be changed here.
curl --fail-with-body https://integrations.allomancy.net/v1/coupons/e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b \
-X PUT \
-H "X-API-Key: allo_live_8Kd2...zQ.Hk9...4w" \
-H "Content-Type: application/json" \
-d '{
"code": "WELCOME15",
"discount": 15,
"ownerProfit": 0,
"active": true,
"bloggersSync": false
}'import requests
response = requests.put(
"https://integrations.allomancy.net/v1/coupons/e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
headers={"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w"},
json={
"code": "WELCOME15",
"discount": 15,
"ownerProfit": 0,
"active": True,
"bloggersSync": False,
},
)
print(response.json())const response = await fetch(
"https://integrations.allomancy.net/v1/coupons/e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
{
method: "PUT",
headers: {
"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w",
"Content-Type": "application/json",
},
body: JSON.stringify({
code: "WELCOME15",
discount: 15,
ownerProfit: 0,
active: true,
bloggersSync: false,
}),
},
);
console.log(await response.json());<?php
$ch = curl_init("https://integrations.allomancy.net/v1/coupons/e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-API-Key: allo_live_8Kd2...zQ.Hk9...4w",
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
"code" => "WELCOME15",
"discount" => 15,
"ownerProfit" => 0,
"active" => true,
"bloggersSync" => false,
]));
$response = curl_exec($ch);
curl_close($ch);
echo $response;The response is the updated CouponResponse. Status: 200, 400, or 404.
Apply a coupon to a customer
POST /v1/customers/{identifier}/actions/apply-couponPre-attaches a coupon to a customer so their next qualifying purchase honors it. Scope: coupons:apply. The {identifier} path parameter is the customer's Second Life username or avatar UUID. The body is an ApplyCouponRequest.
Identify the coupon with exactly one of code, couponOwnerUuid, or couponId. Set scope to 0 for a store-wide application or 1 for a single product; when scope is 1, send the product's UUID in productId, and when scope is 0, omit productId. The application lapses at expiresAt, which is the time of the request plus expiresInHours (optional, defaults to 24, between 1 and 168).
curl --fail-with-body https://integrations.allomancy.net/v1/customers/resident.username/actions/apply-coupon \
-H "X-API-Key: allo_live_8Kd2...zQ.Hk9...4w" \
-H "Content-Type: application/json" \
-d '{
"code": "WELCOME10",
"scope": 1,
"productId": "3a1f0c9b-7d2e-4c84-9a6f-1b5e8d0c2a37",
"expiresInHours": 48
}'import requests
response = requests.post(
"https://integrations.allomancy.net/v1/customers/resident.username/actions/apply-coupon",
headers={"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w"},
json={
"code": "WELCOME10",
"scope": 1,
"productId": "3a1f0c9b-7d2e-4c84-9a6f-1b5e8d0c2a37",
"expiresInHours": 48,
},
)
print(response.json())const response = await fetch(
"https://integrations.allomancy.net/v1/customers/resident.username/actions/apply-coupon",
{
method: "POST",
headers: {
"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w",
"Content-Type": "application/json",
},
body: JSON.stringify({
code: "WELCOME10",
scope: 1,
productId: "3a1f0c9b-7d2e-4c84-9a6f-1b5e8d0c2a37",
expiresInHours: 48,
}),
},
);
console.log(await response.json());<?php
$ch = curl_init("https://integrations.allomancy.net/v1/customers/resident.username/actions/apply-coupon");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-API-Key: allo_live_8Kd2...zQ.Hk9...4w",
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
"code" => "WELCOME10",
"scope" => 1,
"productId" => "3a1f0c9b-7d2e-4c84-9a6f-1b5e8d0c2a37",
"expiresInHours" => 48,
]));
$response = curl_exec($ch);
curl_close($ch);
echo $response;{
"couponId": "e2f3a4b5-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
"code": "WELCOME10",
"discount": 10,
"scope": "product",
"productId": "3a1f0c9b-7d2e-4c84-9a6f-1b5e8d0c2a37",
"customerUuid": "c7d8e9f0-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
"customerUsername": "resident.username",
"expiresAt": "2026-06-17T14:00:00Z",
"replaced": false
}The response is an AppliedCouponResponse. The scope field comes back as the string "store" or "product", even though the request sends it as an integer. replaced is true when the application overwrote an earlier one for the same customer at the same scope. The coupon must be active and not expired. Status: 200; 400 for an invalid body, a coupon-identifier or scope rule violation, an out-of-range expiresInHours, an unresolvable customer or owner, or a coupon that is inactive or expired; 404 if the store, coupon, or product is not found.
Revoke a coupon from a customer
POST /v1/customers/{identifier}/actions/revoke-couponRemoves a coupon application from a customer. Scope: coupons:apply. The {identifier} path parameter is the customer's Second Life username or avatar UUID. The body is a RevokeCouponRequest: the same coupon-identifier and scope rules as apply, without expiresInHours.
curl --fail-with-body https://integrations.allomancy.net/v1/customers/resident.username/actions/revoke-coupon \
-H "X-API-Key: allo_live_8Kd2...zQ.Hk9...4w" \
-H "Content-Type: application/json" \
-d '{
"code": "WELCOME10",
"scope": 1,
"productId": "3a1f0c9b-7d2e-4c84-9a6f-1b5e8d0c2a37"
}'import requests
response = requests.post(
"https://integrations.allomancy.net/v1/customers/resident.username/actions/revoke-coupon",
headers={"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w"},
json={
"code": "WELCOME10",
"scope": 1,
"productId": "3a1f0c9b-7d2e-4c84-9a6f-1b5e8d0c2a37",
},
)
print(response.json())const response = await fetch(
"https://integrations.allomancy.net/v1/customers/resident.username/actions/revoke-coupon",
{
method: "POST",
headers: {
"X-API-Key": "allo_live_8Kd2...zQ.Hk9...4w",
"Content-Type": "application/json",
},
body: JSON.stringify({
code: "WELCOME10",
scope: 1,
productId: "3a1f0c9b-7d2e-4c84-9a6f-1b5e8d0c2a37",
}),
},
);
console.log(await response.json());<?php
$ch = curl_init("https://integrations.allomancy.net/v1/customers/resident.username/actions/revoke-coupon");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-API-Key: allo_live_8Kd2...zQ.Hk9...4w",
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
"code" => "WELCOME10",
"scope" => 1,
"productId" => "3a1f0c9b-7d2e-4c84-9a6f-1b5e8d0c2a37",
]));
$response = curl_exec($ch);
curl_close($ch);
echo $response;{
"revoked": true
}The response is a RevokedCouponResponse. Revoke is idempotent: when no matching application exists, it still returns 200 with revoked set to false. Status: 200; 400 for an invalid body or an unresolvable customer or owner; 404 if the store or coupon is not found.