Introducing our brand new Rules Engine —
Read the docs
LogoLogo
Core APIOther APIsChangelog
Getting started
Getting started
  • Welcome to Commerce Layer
    • Guided setup
    • Manual configuration
  • API specification
  • API credentials
  • Authentication
    • Client credentials
    • Password
    • Authorization code
    • Refresh token
    • JWT bearer
    • Revoking a token
  • Roles and permissions
  • Fetching resources
  • Fetching relationships
  • Including associations
  • Sparse fieldsets
  • Sorting results
  • Pagination
  • Filtering data
  • Creating resources
  • Updating resources
  • Tagging resources
  • Deleting resources
  • Importing resources
  • Exporting resources
  • Cleaning up resources
  • External resources
    • External order validation
    • External prices
    • External shipping costs
    • External payment gateways
    • External promotions
    • External tax calculators
  • Rate limits
  • Handling errors
  • Real-time webhooks
  • Callbacks security
On this page
  • Request
  • Response
  • Security
  1. External resources

External promotions

How to manage custom promotions via external services

PreviousExternal payment gatewaysNextExternal tax calculators

Last updated 4 months ago

Besides the promotion types that are supported out-of-the-box (, , , , , and ) Commerce Layer lets you integrate any kind of promotional engine as an .

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 compliant object you can query to perform your own computation. Aside from the target resource — orders 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": { ... }
    },
    { ... }
  ]
}

Response

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

Applying the discount to all taxable items of the order

The successful response must be a JSON object, returning at least the discount computed by the external logic. If needed, you can optionally enrich the response with some additional information, notification messages, and metadata:

{
  "success": true,
  "data": {
    "name": "My External Promotion",
    "discount_cents": 1500,
    "messages": [ ... ],
    "metadata": {
      "foo": "bar"
    }
  }
}

On error, you must respond with an HTTP code >= 400. The response body must be a JSON object containing any other relevant error code and message:

{
  "success": false,
  "error": {
    "code": "YOUR-ERROR-CODE",
    "message": "Your error message"
  }
}

Applying the discount to specific taxable items

The successful response must be a JSON object, returning at least the discount computed by the external logic to be applied to the specified line items. If needed, you can optionally enrich the response with some additional information, notification messages, and metadata:

{
  "success": true,
  "data": {
    "name": "My External Promotion",
    "discount_cents": 1500,
    "line_items": [
      {
        "id": "kxnXtEaGxo"
      },
      {
        "id": "kXBqtrgARW"
      }
    ],
    "messages": [ ... ],
    "metadata": {
      "foo": "bar"
    }
  }
}

On error, you must respond with an HTTP code >= 400. The response body must be a JSON object containing any other relevant error code and message:

{
  "success": false,
  "error": {
    "code": "YOUR-ERROR-CODE",
    "message": "Your error message"
  }
}

Applying a specific discount to specific taxable items

The successful response must be a JSON object, returning at least a specific discount computed by the external logic to be applied to the specified line items. If needed, you can optionally enrich the response with some additional information, notification messages, and metadata:

{
  "success": true,
  "data": {
    "name": "My External Promotion",
    "line_items": [
      {
        "id": "kxnXtEaGxo",
        "discount_cents": 1000
      },
      {
        "id": "kXBqtrgARW",
        "discount_cents": 500
      }
    ],
    "messages": [ ... ],
    "metadata": {
      "foo": "bar"
    }
  }
}

On error, you must respond with an HTTP code >= 400. The response body must be a JSON object containing any other relevant error code and message:

{
  "success": false,
  "error": {
    "code": "YOUR-ERROR-CODE",
    "message": "Your error message"
  }
}

If you are going to specify the discount_cents key for the single line items, make sure to do it for all of the elements of the line_items array. Keep in mind that the promotion amount is computed and distributed only for the line items whose IDs are listed in the array with a discount_cents key specified. In this case, avoid adding the discount_cents key at order the level because it's ignored if there is any line item with a specific discount_cents key set.

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.

In case the call to your external endpoint goes timeout, responds with an internal server error, or is blocked by the open , 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.

Be aware that specifying the line items in the response will overwrite both the associated SKU list (if any) and the 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.

If you specify the messages key a with the related information is automatically attached to the associated order.

Callbacks security
fixed amount
fixed price
free gift
free shipping
percentage discount
external promotion
JSON:API
circuit breaker
notification
buy X pay Y
taxable items