Docs
Firmly Agentic Commerce
Set theme to dark (⇧+D)

Add Promo Codes

POST https://api.firmly.work/api/v2/domains/{domain}/cart/promo-codes

Applies one or more promotional codes to the cart. The merchant validates each code and applies any eligible discount. The response is the updated cart with applied codes in coupons and recalculated totals.

​​ Authentication

  • x-firmly-authorization (string, required) — Device access token from Browser Session

​​ Path Parameters

  • domain (string, required) — The merchant’s domain (e.g. staging.luma.gift).

​​ Request Body

  • promo_codes (string[], required) — Array of promotional codes to apply. Length 1–10. Each entry is a non-empty trimmed string.

​​ Response

Returns the full cart (same schema as Get Cart). Promotion-relevant fields after a successful apply:

  • coupons — array of currently applied codes (strings).
  • cart_discount — total discount applied to the cart (Amount).
  • cart_discount_breakdown — per-promotion breakdown (when the merchant exposes it).
  • line_items[].discount / line_items[].line_discount — per-line amounts (when the merchant exposes them).
  • sub_total, tax_total, total — recalculated.

​​ Examples


curl -X POST https://api.firmly.work/api/v2/domains/staging.luma.gift/cart/promo-codes \
-H "x-firmly-authorization: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"promo_codes": ["SAVE20"]
}'

curl -X POST https://api.firmly.work/api/v2/domains/staging.luma.gift/cart/promo-codes \
-H "x-firmly-authorization: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"promo_codes": ["SAVE20", "FREESHIP", "LOYALTY10"]
}'

const response = await fetch('https://api.firmly.work/api/v2/domains/staging.luma.gift/cart/promo-codes', {
method: 'POST',
headers: {
'x-firmly-authorization': 'YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
promo_codes: ['SAVE20']
})
});
const cart = await response.json();

import requests
response = requests.post(
'https://api.firmly.work/api/v2/domains/staging.luma.gift/cart/promo-codes',
headers={
'x-firmly-authorization': 'YOUR_TOKEN',
'Content-Type': 'application/json'
},
json={'promo_codes': ['SAVE20']}
)
cart = response.json()

​​ Response Example


{
"cart_id": "a5600193-2c13-3356-d063-711da63b7cd7",
"platform_id": "example_commerce",
"shop_id": "staging.luma.gift",
"cart_status": "active",
"line_items": [
{
"line_item_id": "bd3710bc-97ef-408d-7382-43b7e5de712f",
"sku": "WS12-XS-Orange",
"description": "Radiant Tee",
"quantity": 2,
"price": { "currency": "USD", "value": 22.00, "number": 2200, "symbol": "$" },
"line_price": { "currency": "USD", "value": 44.00, "number": 4400, "symbol": "$" },
"msrp": { "currency": "USD", "value": 28.00, "number": 2800, "symbol": "$" },
"discount": { "currency": "USD", "value": 10.00, "number": 1000, "symbol": "$" },
"line_discount": { "currency": "USD", "value": 20.00, "number": 2000, "symbol": "$" },
"image": {
"url": "https://staging.luma.gift/radiant-tee.jpg",
"alt": "Radiant Tee",
"type": "default"
},
"requires_shipping": true
}
],
"coupons": ["SAVE20"],
"sub_total": { "currency": "USD", "value": 44.00, "number": 4400, "symbol": "$" },
"cart_discount": { "currency": "USD", "value": 20.00, "number": 2000, "symbol": "$" },
"shipping_total": { "currency": "USD", "value": 9.99, "number": 999, "symbol": "$" },
"tax_total": { "currency": "USD", "value": 2.40, "number": 240, "symbol": "$" },
"fees": [{ "description": "Recycle fee", "currency": "USD", "value": 2.00, "number": 200, "symbol": "$" }],
"fee_total": { "currency": "USD", "value": 2.00, "number": 200, "symbol": "$" },
"total": { "currency": "USD", "value": 38.39, "number": 3839, "symbol": "$" },
"schema_version": "2.0"
}

​​ Error Responses

Errors return a JSON body with code, error, and description. Program against the error value — descriptions are human-readable and may change.

400 — MissingAuthHeader

The x-firmly-authorization header is missing or empty.


{ "code": 400, "error": "MissingAuthHeader", "description": "x-firmly-authorization header is missing or invalid." }
400 — InvalidToken

The authorization token is not a valid JWT structure.


{ "code": 400, "error": "InvalidToken", "description": "Jwt token is invalid." }
400 — InvalidAPIToken

The API token (server-to-server secret) is invalid or has been revoked.


{ "code": 400, "error": "InvalidAPIToken", "description": "API token is invalid." }
400 — BadRequest

Server-to-server auth was attempted but required headers are missing or malformed.


{ "code": 400, "error": "BadRequest", "description": "Bad request." }
401 — Unauthorized

The authorization token was rejected.


{ "code": 401, "error": "Unauthorized", "description": "Unauthorized." }
401 — InvalidJWTToken

The device JWT signature does not verify, or required claims are missing.


{ "code": 401, "error": "InvalidJWTToken", "description": "Jwt token is invalid." }
404 — PartnerNotFound

The appid claim on the device JWT does not map to a known partner / tenant.


{ "code": 404, "error": "PartnerNotFound", "description": "Partner not found." }
404 — DomainNotFound

The {domain} path parameter does not match any merchant configured with Firmly, or the merchant has been disabled.


{ "code": 404, "error": "DomainNotFound", "description": "This domain was not found in firmly servers." }
404 — CartNotFound

No cart exists for this device on this domain. Add an item first via Add Line Item.


{ "code": 404, "error": "CartNotFound", "description": "Cart was not found." }
409 — InvalidPromoCode

One or more codes are invalid, expired, or not recognized by the merchant.


{ "code": 409, "error": "InvalidPromoCode", "description": "Invalid promo code." }
409 — PromoNotAvailable

The code exists but is not available for the current cart (e.g. minimum-purchase not met, product-restricted, customer-segment-restricted).


{ "code": 409, "error": "PromoNotAvailable", "description": "Promo is not available." }
409 — MultipleDiscountCodesNotSupported

The merchant does not allow more than one discount code to be applied at once, but the request (or the resulting cart) would carry multiple codes. Apply a single code instead.


{ "code": 409, "error": "MultipleDiscountCodesNotSupported", "description": "Multiple discount codes are not supported." }
412 — OperationNotSupported

The merchant’s platform does not support applying promo codes via API.


{ "code": 412, "error": "OperationNotSupported", "description": "This operation is not supported for this store." }
400 — InvalidInputBody

Request body fails schema validation. promo_codes must be an array of 1–10 non-empty trimmed strings.


{ "code": 400, "error": "InvalidInputBody", "description": "The body is not processable" }