borkoldocs

Carts & Checkout

Discount codes

Attach a discount code to a cart, understand lazy evaluation and error codes, and remove the code.

View as Markdown

A cart carries at most one discount code. The code is stored verbatim and evaluated lazily on every cart read: attaching an unusable code does not fail the request. Instead, every cart response reports the outcome through two fields:

  • discount_code_error: null when the code applies (or no code is set), otherwise one of the values below.
  • discounts[]: the list of discounts currently applied to the cart, each as {id, name, code, kind, amount} where kind is one of order, products, shipping, bogo and amount is an integer in minor units. Automatic (codeless) discounts also appear here.
discount_code_errorMeaning
invalidNo discount with this code exists (or it is inactive).
expiredThe discount's validity window has passed or not started.
min_orderThe cart total is below the discount's minimum order value.
not_eligibleThe cart or customer does not match the discount's conditions.
usage_limitThe discount's usage limit is exhausted.

Because evaluation is lazy, a code that is valid today can become expired or usage_limit later; re-read the cart to get the current state. Usage limits are additionally re-checked under a lock at checkout: a code exhausted between attach and checkout causes a 409 cart conflict with a discount_unavailable entry (see the Checkout page).

Both endpoints require commerce:write, an active cart, and pass the cart ownership check. Both return the full cart envelope, the same shape as GET /v1/api/commerce/carts/{id}.

PUT /v1/api/commerce/carts/{id}/discount-code

Attaches a discount code to the cart, replacing any previously attached code. The request succeeds for any well-formed code; check discount_code_error and discounts[] in the response to see whether it applied.

Parameters

Path

NameTypeRequiredDescription
idstring (UUID)yesCart id. Must be an active cart.

Body

NameTypeRequiredDescription
codestringyesMax 100 characters, must be non-blank after trimming.
Request
curl -X PUT https://api.borkol.com/v1/api/commerce/carts/9d3f2a10-6b7c-4e6d-9f21-8a54c1d2e3f4/discount-code \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{"code": "WELCOME10"}'
Request (JS)
const res = await fetch(
  `https://api.borkol.com/v1/api/commerce/carts/${cartId}/discount-code`,
  {
    method: "PUT",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ code: "WELCOME10" }),
  }
);
const { data: cart } = await res.json();
if (cart.discount_code_error) {
  // show why the code did not apply: invalid | expired | min_order | not_eligible | usage_limit
}
Response
{
  "data": {
    "id": "9d3f2a10-6b7c-4e6d-9f21-8a54c1d2e3f4",
    "discount_code": "WELCOME10",
    "discount_code_error": null,
    "discounts": [
      {
        "id": "71c9e0aa-2f4b-4d31-9a77-0b1c2d3e4f5a",
        "name": "Welcome 10%",
        "code": "WELCOME10",
        "kind": "order",
        "amount": 450
      }
    ],
    "...": "same cart shape as GET /v1/api/commerce/carts/{id}"
  }
}

When the code cannot apply, the response is still 200 with, for example, "discount_code": "SUMMER24", "discount_code_error": "expired", "discounts": [].

Errors

StatusBodyWhen
422{"message": "...", "errors": {"code": ["..."]}}Code missing, blank after trim, or longer than 100 characters.
404{"message": "..."}Cart unknown, expired, or not active.
403ownership, scope, module, or suspension bodySee the Carts page.
429{"message": "Too Many Attempts."}Rate limit exceeded.

DELETE /v1/api/commerce/carts/{id}/discount-code

Removes the discount code from the cart. Automatic (codeless) discounts are unaffected and may still appear in discounts[].

Parameters

Path

NameTypeRequiredDescription
idstring (UUID)yesCart id. Must be an active cart.

No body.

Request
curl -X DELETE https://api.borkol.com/v1/api/commerce/carts/9d3f2a10-6b7c-4e6d-9f21-8a54c1d2e3f4/discount-code \
  -H "Authorization: Bearer {api_key}"
Response
{
  "data": {
    "id": "9d3f2a10-6b7c-4e6d-9f21-8a54c1d2e3f4",
    "discount_code": null,
    "discount_code_error": null,
    "...": "same cart shape as GET /v1/api/commerce/carts/{id}"
  }
}

Errors

StatusBodyWhen
404{"message": "..."}Cart unknown, expired, or not active.
403ownership, scope, module, or suspension bodySee the Carts page.
429{"message": "Too Many Attempts."}Rate limit exceeded.