Promotions Mapper

Send data between your coupon monitoring tools and Nacelle.

Use the Promotions Mapper to link your coupon monitoring tools to Nacelle, like Voucherify and Talon.One.

Custom connector

To begin the data mapping process, start by granting your coupon monitoring tool permission to send and pull data to and from Nacelle with the custom connector token. Set up a custom connector in the Nacelle dashboard.

Validate the contract

Description: This API is used to retrieve or validate your cart based promotions during the checkout session.

📘

Note: Nacelle returns the mutated checkout object to the merchant after all other validations have run. You can then transform the model as needed in the front end.

REST API contract:

Merchant Supplied Endpoint: Start by finding the endpoint your promotions tool uses to send and receive data.

Example

https://merchant-mapper.com/promotions/validate

HTTP Method: POST

Request Format

  • Headers:
    • Content-Type: application/json: Specifies that the request body contains JSON data
    • x-nacelle-signature-sha256: The signed payload signature. This is an HMAC signature. The secret can be retrieved from the Nacelle dashboard.
    • (Optional authentication headers)
  • Request Body (JSON): Based on the (Checkout) endpoint
{  
   ...  
   "items": [  
     {  
       ...  
       "product_id": "my-product-id",
       "variant_id": "my-variant-id",
       "sku": "SKU1234",  
       "quantity": 1,  
       "price": "140.00",  
     }  
   ],  
   "promotions":{  
     "coupon_codes": ["XMAS-2021-25"],  
     "referral_code":"",  
     "loyalty_card":"",  
     "identifiers":["91.11.156.141"],  
     "meta":{} //additional details as needed  
   }  
 }

Response format

  • Status Code:
    • 200 OK - The request was successful, and the checkout has been updated.
    • 400 Status Bad Request - If the object is missing required data
    • 401 Unauthorized - If authentication is required and not provided.
    • 403 Forbidden - If the user does not have permission to update the task.
    • 422 Unprocessable Content - if the promotion encountered an issue in 3rd party promotion engine
Response body (JSON)

Based on the (Response Model Reference )

{  
  "checkout": { 
    ...  
    "total_discount": "35.00", //total discount amount across all discounts  
    "items": \[  
      {  
        ...  
        "product_id": "my-product-id",
        "variant_id": "my-variant-id", 
        "sku": "SKU1234",  
        "quantity": 1,  
        "price": "105.00", //Updated price amount  
        "total_discount":"35.00", //total order item discount accross all discounts on this order item  
        "discounts":[ //item level discounts if applicale  
        {  
          "name":"XMAS coupon",  
          "description":"$35 off items over $100",  
          "amount":"35.00",  
          "effect_type":"setDiscountPerItem",  
          "meta":{  
            "campaignId": 3882,  
            "rulesetId": 14828,  
            "triggeredByCoupon": 4607465,  
          }  
        }  
        ]  
      }  
    ],  
    "discounts":\[], //order level discounts if applicable  
    "promotions":{  
      "coupon_codes": ["XMAS-2021-25"],  
      "referral_code":"",  
      "loyalty_card":"",  
      "identifiers":["91.11.156.141"],  
      "meta":{} //additional details as needed  
    },
  }
}

The response body contains the updated cart object specifying the discount amounts and adjusting the price as required.

Error handling (JSON)

Based on the (Response Model Reference )

{  
  "checkout": {},  
  "error": {  
    "error": "Promotion Code Invalid",  
    "category": "promotion_codes",  
    "details": {  
      "invalid-code": "XMAS-2021-25"  
    }  
  }  
}

The response body includes an error field containing a descriptive error message and a category with optional details. The category should be used to give the client information on how to parse the details section. For more information, see Error Responses in the Response model reference.

Consume the contract

Description: Use this API to consume the promotions after the payment is processed. Run it as part of the order creation process.

REST API contract:

Merchant supplied endpoint:

Example

https://merchant-mapper.com/promotions/consume

HTTP Method: POST

Request format:

  • Headers:
    • Content-Type: application/json: Specifies that the request body contains JSON data
    • x-nacelle-signature-sha256: The signed payload signature. This is an HMAC signature. The secret can be retrieved from the Nacelle dashboard.
    • (Optional authentication headers)
  • Request Body (JSON): Based on the (Create a multi-order) endpoint
{
  ...
  "discounts": "35.00", //total discount amount across all discounts
  "order_items": [
    {
      ...
      "product_id": "my-product-id",
      "variant_id": "my-variant-id",
      "sku": "SKU1234",
      "quantity": 1,
      "price_amount": "105.00", //Updated price amount
      "discounts_amount":"35.00" //total order item discount accross all discounts on this order item
      "applied_discounts":[ //item level discounts if applicale
        {
          "name":"XMAS coupon",
          "description":"$35 off items over $100",
          "amount":"35.00",
          "effect_type":"setDiscountPerItem",
          "meta":{
            "campaignId": 3882,
            "rulesetId": 14828,
            "triggeredByCoupon": 4607465,
          }
        }
      ]
    }
  ],
  "applied_discounts":[], //order level discounts if applicable
  "promotions":{
    "coupon_codes": ["XMAS-2021-25"],
    "referral_code":"",
    "loyalty_card":"",
    "identifiers":["91.11.156.141"],
    "meta":{} //additional details as needed
  }
 }

Response Format:

  • Status Code:
    • 200 OK - The request was successful, and the 3rd party promotion engine has handled the request
    • 400 Status Bad Request - If the object is missing required data
    • 401 Unauthorized - If authentication is required and not provided.
    • 403 Forbidden - If the user does not have permission to update the task.
    • 500 Internal Server Error - if the promotion encountered an issue in 3rd party promotion engine
Response body (JSON)

Based on the(Response Model Reference )

{
  "order": {...},
}

The response body indicates that the 3rd party promotion engine successfully acknowledged the completion of the promotion.

Error Handling (JSON)

Based on the(Response Model Reference )

{
  "order": {},
  "error": {
    "error": "Promotion Code Invalid",
    "category": "promotion_codes",
    "details": {
      "invalid-code": "XMAS-2021-25"
    }
  }
}

The response body includes an error field containing a descriptive error message, and a category with optional details. The category should be used to give the client information on how to parse the details section. For more information, see Error Responses in the Response model reference.

Validating promotions workflow

[Merchant] Call the validation mutation

The merchant calls an endpoint in Nacelle to validate the checkout using a REST API method which returns the updated checkout after running validation steps:


<https://noms.api.nacelle.com/api/v1/checkout/validate>
--header 'Authorization: Bearer <merchant-auth-token>'  
--header 'x-nacelle-space-id: <merchant-space-id>'  
--header 'Content-Type: application/json'  
--data-raw '{  
  ...  
  "items": [  
     {  
       ...  
       "product_id": "my-product-id",
       "variant_id": "my-variant-id", 
       "sku": "SKU1234",  
       "quantity": 1,  
       "price": "140.00",  
     }  
   ],  
   "promotions":{  
     "coupon_codes": ["XMAS-2021-25"],  
     "referral_code":"",  
     "loyalty_card":"",  
     "identifiers":["91.11.156.141"],  
     "meta":{} //additional details as needed  
   }    
}'

[Nacelle] Call the merchant mapper

The Nacelle Orchestration layer calls the merchant endpoint:

https://merchant-mapper.com/promotions/validate
--header 'Secret: some secret header'  
--header 'Content-Type: application/json'  
--data-raw '{  
  ...  
  "items": [  
    {  
      ...  
      "product_id": "my-product-id",
      "variant_id": "my-variant-id",
      "sku": "SKU1234",  
      "quantity": 1,  
      "price": "140.00",  
    }  
  ],  
  "promotions":{  
    "coupon_codes": ["XMAS-2021-25"],  
    "referral_code":"",  
    "loyalty_card":"",  
    "identifiers":["91.11.156.141"],  
    "meta":{} //additional details as needed  
  }  
}'

[Merchant] Merchant mapper convert checkout

You then need to convert the checkout object into the required format for the 3rd party promotion engine.

[Merchant] Call the promotion engine

Then call the 3rd party promotion engine to create a session with cart items and coupon codes by specifying the state as open.

Talon.One Example

curl --request PUT 'https://myapp.europe-west1.talon.one/v2/customer_sessions/mysession'
--header 'Authorization: ApiKey-v1 \<your_api_key>'  
--header 'Content-Type: application/json'  
--data-raw '{  
 "customerSession": {  
   "state": "open",  
   "cartItems": [  
     {  
       "name": "Mountain Bike",  
       "sku": "SKU1234",  
       "quantity": 1,  
       "price": 140,  
       "category": "bikes", //use variant id to pull additional product information as required  
       "weight": 10  
     }  
   ],  
   "additionalCosts": {  
     "shipping": {  
       "price": 15  
     }  
   },  
   "couponCodes": ["XMAS-2021-25"]  
   ... other fields as required  
 },  
 "responseContent": [  
   "customerSession",  
   "customerProfile",  
   "triggeredCampaigns",  
   "coupons"  
 ]  
}'

Depending on merchant settings in Talon.One, a coupon could apply to order items or to an entire order. This would be based on the effects Talon.One returns. See the effects resource for other possible effects.

[Merchant] Handle the promotion response

Once the merchant returns the response from their promotion engine, the merchant then applies the effects to the Nacelle order object. Some possible effects are listed below.

[Merchant] Reconstruct the checkout object

Once the merchant has successfully retrieved the response from their promotion engine they will use the response to update the checkout and return it from their endpoint as the response body.

{ 
  "checkout":
  {
   ...  
   "total_discount": "50.00", //total discount amount across all order items and additional costs  
   "items": \[  
     {  
       ...  
       "product_id": "my-product-id",
       "variant_id": "my-variant-id",
       "sku": "SKU1234",  
       "quantity": 1,  
       "price": "105.00", //Updated price amount  
       "total_discount": "35.00", //Discount amount of this order item  
       "discounts":[ //item level discounts if applicale  
        {  
          "name":"XMAS coupon",  
          "description":"$35 off items over $100",  
          "amount":"35.00",  
          "effect_type":"setDiscountPerItem",  
          "meta":{  
            "campaignId": 3882,  
            "rulesetId": 14828,  
            "triggeredByCoupon": 4607465,  
          }  
        }  
       ]  
     }  
   ],  
   "discounts":[ //item level discounts if applicale  
     {  
       "name":"Free shipping over $100 orders",  
       "description":"100% off shipping cost on carts over $100",  
       "amount":"15.00",  
       "effect_type":"setDiscountPerAdditionalCost",  
       "meta":{  
         "campaignId": 3882,  
         "rulesetId": 14829,  
       }  
     }  
   ],  
   "promotions":{  
     "coupon_codes": ["XMAS-2021-25"],  
     "referral_code":"",  
     "loyalty_card":"",  
     "identifiers":["91.11.156.141"],  
     "meta":{} //additional details as needed  
   }  
 }
}	

[Nacelle] Continue with the orchestration flow

checkoutWithPromotionChanges, err := merchantMapperConfig.promotion.validate(checkout)

Nacelle continues to process the other steps in the orchestration flow with the updated checkout. If the merchant encounters an error, we return the error back to the client for the merchant to handle the issue.

[Nacelle] Return to the merchant

Once all the steps in the orchestration layer finish, Nacelle returns the updated checkout to the merchant as the data requested from the GraphQL mutation.

[Merchant] Final steps

If additional cart changes occur and need to be revalidated, the merchant calls the mutation to validate the cart again. Once a cart is finalized and ready to be converted into an order, the merchant uses this updated checkout to collect payment from their payment provider and send the order details to the Nacelle /multiorders endpoint. Nacelle then runs through the consume orchestration methods.

Consuming the promotions workflow

[Merchants] Call the create orders endpoint

Call the /multiorders endpoint in Nacelle to create an order using the REST API:

<https://noms.api.nacelle.com/api/v1/multiorders> 
--header 'Authorization: Bearer <merchant-auth-token>'  
--header 'x-nacelle-space-id: <merchant-space-id>'  
--header 'Content-Type: application/json'  
--data-raw '{  
  ...  
  "discounts": "50.00", //total discount amount across all order items and order level discounts  
  "order_items": \[  
    {  
      ...  
      "product_id": "my-product-id",
      "variant_id": "my-variant-id",
      "sku": "SKU1234",  
      "quantity": 1,  
      "price": "105.00",  
      "discounts": "35.00", //total discount amount of this order item  
      "applied_discounts":[ //item level discounts if applicale  
      {  
        "name":"XMAS coupon",  
        "description":"$35 off items over $100",  
        "amount":"35.00",  
        "effect_type":"setDiscountPerItem",  
        "meta":{  
          "campaignId": 3882,  
          "rulesetId": 14828,  
          "triggeredByCoupon": 4607465,  
        }  
      }  
    }  
  ],  
  "applied_discounts":[ //order level discounts if applicale  
    {  
      "name":"Free shipping over $100 orders",  
      "description":"100% off shipping cost on carts over $100",  
      "amount":"15.00",  
      "effect_type":"setDiscountPerAdditionalCost",  
      "meta":{  
        "campaignId": 3882,  
        "rulesetId": 14829,  
      }  
    }  
  ],  
  "promotions":{  
    "coupon_codes": ["XMAS-2021-25"],  
    "referral_code":"",  
    "loyalty_card":"",  
    "identifiers":["91.11.156.141"],  
    "meta":{} //additional details as needed  
  }  
}'

[Nacelle] Call the merchant mapper

Nacelle then uses its orchestration layer to call an endpoint:

https://merchant-mapper.com/promotions/consume 
--header 'Secret: some secret/validation header to tell the merchant this is coming from a trusted source'  
--header 'Content-Type: application/json'  
--data-raw '{  
  ...  
  "discounts": "50.00",  
  "order_items": \[  
    {  
      ...  
      "product_id": "my-product-id",
      "variant_id": "my-variant-id",
      "sku": "SKU1234",  
      "quantity": 1,  
      "price": "105.00",  
      "discounts": "35.00", //total discount amount of this order item  
      "applied_discounts":[ //item level discounts if applicale  
      {  
        "name":"XMAS coupon",  
        "description":"$35 off items over $100",  
        "amount":"35.00",  
        "effect_type":"setDiscountPerItem",  
        "meta":{  
          "campaignId": 3882,  
          "rulesetId": 14828,  
          "triggeredByCoupon": 4607465,  
        }  
      }  
    }  
  ],  
  "applied_discounts":[ //order level discounts if applicale  
    {  
      "name":"Free shipping over $100 orders",  
      "description":"100% off shipping cost on carts over $100",  
      "amount":"15.00",  
      "effect_type":"setDiscountPerAdditionalCost",  
      "meta":{  
        "campaignId": 3882,  
        "rulesetId": 14829,  
      }  
    }  
  ],  
  "promotions":{  
    "coupon_codes": ["XMAS-2021-25"],  
    "referral_code":"",  
    "loyalty_card":"",  
    "identifiers":["91.11.156.141"],  
    "meta":{} //additional details as needed  
  }  
}'

[Merchants] Merchant mapper converts the order

You then need to convert the checkout object into the format that your promotion engine requires.

[Merchants] Call the promotion engine

You then call your promotion engine to finalize the orders promotions.

Talon.one Example

The merchants then calls Talon.One to close the session:

curl --request PUT 'https://myapp.europe-west1.talon.one/v2/customer_sessions/mysession'  
--header 'Authorization: ApiKey-v1 \<your_api_key>'  
--header 'Content-Type: application/json'  
--data-raw '{  
 "customerSession": {  
   "state": "closed",  
   "cartItems": [  
     {  
       "name": "Mountain Bike",  
       "sku": "SKU1234",  
       "quantity": 1,  
       "price": 105,  
       "discounts": 35  
       "category": "bikes",  
       "weight": 10  
     }  
   ],  
   "additionalCosts": {  
     "shipping": {  
       "price": 0  
     }  
   },  
   "couponCodes": ["XMAS-2021-25"]  
 },  
 "responseContent": [  
   "customerSession",  
   "customerProfile",  
   "triggeredCampaigns",  
   "coupons"  
 ]  
}

This marks the session as closed. A 200 ok or an error is returned back to Nacelle.

[Nacelle] Continue with the orchestration flow

err := merchantMapperConfig.promotion.consume(order)

If Nacelle encounters an error during any of the orchestration steps, we stop the orchestration flow and respond to the merchant with the error. Otherwise we continue to process other steps in the orchestration flow with the order.