External promotions

How to manage custom promotions via external services

Besides the promotion types that are supported out-of-the-box (buy X pay Y, fixed amount, fixed price, free gift, free shipping, and percentage discount) Commerce Layer lets you integrate any kind of promotional engine as an external promotion.

When an external promotion activates — i.e. its activation rules are met — Commerce Layer triggers a POST request to the promotion_url endpoint, sending the order payload (including its line items) in the request body.

Request

The request payload is a JSON:API compliant object you can query to perform your own computation. Aside from the target resourceorders in the specific case — some relationships are also included to avoid useless API roundtrips:

  • market

  • customer

  • customer.tags

  • line_items

  • line_items.item

  • shipping_address

  • billing_address

{
  "data": {
    "id": "wBXVhKzrnq",
    "type": "orders",
    "links": { ... },
    "attributes": { ... },
    "relationships": { ... },
    "meta": { ... }
  },
  "included": [
    {
      "id": "DvlGRmhdgX",
      "type": "markets",
      "links": { ... },
      "attributes": { ... },
      "relationships": { ... },
      "meta": { ... }
    },
    {
      "id": "bGvCXzYgNB",
      "type": "customers",
      "links": { ... },
      "attributes": { ... },
      "relationships": { ... },
      "meta": { ... }
    },
    {
      "id": "YawgnfmKad",
      "type": "tags",
      "links": { ... },
      "attributes": { ... },
      "relationships": { ... },
      "meta": { ... }
    },
    {
      "id": "kdPgtRXOKL",
      "type": "line_items",
      "links": { ... },
      "attributes": { ... },
      "relationships": { ... },
      "meta": { ... }
    },
    {
      "id": "XGZwpOSrWL",
      "type": "skus",
      "links": { ... },
      "attributes": { ... },
      "relationships": { ... },
      "meta": { ... }
    }
    {
      "id": "BgnguJvXmb",
      "type": "addresses",
      "links": { ... },
      "attributes": { ... },
      "relationships": { ... },
      "meta": { ... }
    },
    {
      "id": "AlrkugwyVW",
      "type": "addresses",
      "links": { ... },
      "attributes": { ... },
      "relationships": { ... },
      "meta": { ... }
    },
    { ... }
  ]
}

In case the call to your external endpoint goes timeout, responds with an internal server error, or is blocked by the open circuit breaker, the API keeps responding with a 200 OK status code. No promotion is added to the order and the circuit breaker internal counter (if closed) is incremented.

Response

Your service response (or error) must match the format described in the example below.

The successful response must be a JSON object, returning the discount computed by the external logic, optionally the list of line item IDs on which to distribute the discount, along with some additional information and metadata:

{
  "success": true,
  "data": {
    "name": "My External Promotion",
    "discount_cents": 1500,
    "matching_line_item_ids": ["hBfCxzWQgU", "pLkJjHrEwQ"],
    "metadata": {
      "foo": "bar"
    }
  }
}

The matching_line_item_ids attribute is optional. You can add it if you want to distribute the external promotion discount only on specific line items (it must include all of the IDs of the line items with positive amount on which you want the discount to be distributed).

Be aware that specifying the matching line items in the response will overwrite both the associated SKU list (if any) and the taxable items options (e.g. you can distribute the discount on a purchased gift card also if the gift_card_taxable is false). In case any of the provided line item IDs is not associated with the order, no promotion is applied.

Security

When you create a new external promotion, a shared secret is generated. We recommend verifying the callback authenticity by signing the payload with that shared secret and comparing the result with the callback signature header.

pageCallbacks security

Last updated