Library OpenApi Overview About these APIs Architecture Authentication Error Responses Locating a Server Sessions Design Guides Guides and Hints Examples Pricing for Websites Accepting Vouchers PreAuth Payment Replication Common Apis The most used APIs Create New Sale Payment Completion Multiple Locations Delivery Addresses Customers Locations Products Staff WebHooks eCommerce Apis These APIs are often used with eCommerce website integrations Get Pricing Card Inquiry Report & Analysis Grouped or analysed report data. Typically used to build reports and dashboards Today Login Access Pinboard ReportRequest Advanced Information More indepth information Caller Handling HTTP Protocol Bulk Data Downloads Document Uploading RetailConfig Under Development Details of APIs that will be available shortly. Documentation provided is for early adopters Get Receipt

Get Pricing API

This API permits sale capture applications to retrieve current pricing for a sale without having to implement price calculations themselves. Often retailers have pricing that goes beyond the simple X costs $y. By calling this API with your sale you effectively offload this calculation to the server and ensure that eCommerce sites match instore pricing. The intention is that this API is called whenever something material changes within a sale while it is being actively created.

Your Cart » Creates Sale_Create object » Calls /Sales/Pricing API » Extracts pricing and instructions
from Sale_Pricing response
» Updates your cart

Simple Examples

The smallest possible call to this API is simply to supply a Product Id and the price for a cash/unknown customer will be returned

Request

{
  "Saleline": [
    {
      "Pid": 16
    }
  ]
}

Reply

{
  "data": {
    "Sale_Create": [
      {
        "PriceToken": "KEPZFLMAZZRE897FE5GEAJAAAACQAAAB",
        "Saleline_Create": [
          {
            "Pid": 16,
            "Qty": 0,
            "TotalPrice": "260.000000",
            "Sale_PricingInfo": [
              {
                "PriceTrace": "TicketPrice=260.0000",
                "CopyField": [
                  "TotalPrice"
                ]
              }
            ]
          }
        ]
      }
    ]
  }
}

Minimally get a Price

    {
        "Customer": 2345,
        "LINE": [{
                "Pid": 12345,
                "Qty": 2,
                "Sequence": 1
            }]
    }
    

Create a Sale_Create object, with only the information you know. The Pricing API ignores fields it does not need or understand

For a simple price lookup the response will be


{
  "data": {
    "Sale_Create": [
      {
        "PriceToken": "KEPZFK9AZZRE897FPZ95QPAAAAAQAAAB",       « Unique identifier for this API call
        "CustomerId": 2345,
        "Saleline_Create": [
          {
            "Pid": 12345,
            "Qty": 2,
            "TotalPrice": "298.000000",     « Price to Charge
            "Sale_PricingInfo": [           « Extra Information
              {
                "CopyField": "TotalPrice",
                "PriceTrace": "TicketPrice=298.0000"
              }
            ]
          }
        ]
      }
    ]
  }
}


Should special pricing currently be in effect, lets say buy 2 for $15, the response changes and includes the extra fields


{
  "data": {
    "Sale_Create": [
      {
        "PriceToken": "KEPZFK9AZZRE897FPZ95QPAAAAAQAAAC",       « Unique identifier for this API call
        "CustomerId": 2345,
        "Saleline_Create": [
          {
            "Pid": 12345,
            "Qty": 2,
            "TotalPrice": "15.000000",      « Price to Charge
            "PriceCause": 3,
            "PriceCauseData": 523,
            "PricingComment": "2 for $15 this month",
            "Sale_PricingInfo": [           « Extra Information
              {
                "CopyField": ["TotalPrice", "PriceCause", "PriceCauseData" ],
                "PriceTrace": "TicketPrice=298.0000|Kit=523"
              }
            ]
          }
        ]
      }
    ]
  }
}


Sale_PricingInfo

Each Saleline processed will contain a Sale_PricingInfo structure that supplies additional information about the pricing operation

CopyField

This field is an array (and always an array even if it only contains one element) of fields that have been added to the saleline that should be copied into your final Sale_Create object to save the sale.

"Saleline_Create": [ {
  "Pid": 12345,
  "Qty": 2,
  "TotalPrice": "15.000000",    « Copy this field
  "PriceCause": 3,              « Copy this field
  "PriceCauseData": 523,        « Copy this field
  "PricingComment": "2 for $15 this month",       « No need to copy
  "Sale_PricingInfo": [ {
    "CopyField": ["TotalPrice", "PriceCause", "PriceCauseData" ],
    "PriceTrace": "TicketPrice=298.0000|Kit=523",
    "Method": "linear"
  }]}]

PriceTrace

This is an internal field that should not be shown to customers. It contains technical details about how the price was derived and can be helpful to support staff to understand the steps

Method

This field indicates how pricing is derived. If this field contains the value "linear" then pricing for this item is not affected by other items on the sale and you can simply multiply quantity by each price to obtain totalprice if your prefer. This allows you to save API calls, especially as linear pricing is very common. If you change other data, such as Customer or store, then you must reprice the sale as linear pricing may have been specific to those values.

Logically Handling an Active Cart

The PricingAPI consumes a Sale_Create object the same as the /Sales API to actually store the sale, however its response might not be immediately suitable to send to /Sales API

Your Cart » Creates Sale_Create object
(aka "YourSale")
» Calls /Sales/Pricing API » Extracts pricing and instructions
from Sale_Pricing response
(aka "PricingSale")
» Updates your cart » Saves the Sale
(aka "FinalSale")

There are a few strategies for handling the steps highligthed in yellow

Do NOT simply replace "YourSale" with the "PricingSale". You should maintain and update "YourSale" and only use "PricingSale" to generate the final step. The reason is that if you send pricing information into the GetPricing API, it may obey that first. So if subsequent changes to the sale might have caused the pricing of an item to change, you supplying the price will block this change being applied.

Option 1 - Merge "YourSale"

The output from the PricingApi should be able to be passed into the /Sales API to save the sale, however you are strongly advised to check this especially if "YourSale" has uncommon fields or objects. The /Sales API to save the sale will ignore the additional fields and objects such as Sale_PricingInfo

  1. Start with the first element in the Sale_Create array as the final sale e.g.
    var FinalSale = PricingSale.data.Sale_Create[0];
    
  2. Loop over "YourSale" and copy any fields not present in "FinalSale" into FinalSale
  3. Add other required fields not already present, if any

Option 2 - Extract Key Data

  1. For each Saleline returned in "PricingSale"
  2. Copy all the fields to your "FinalSale" that are listed in the Sale_PricingInfo[0].CopyField array
  3. Do not copy these fields back to "YourSale", as this will cause pricing to lock to that value as other things change in the sale which might affect the pricing.
  4. Also Copy "PriceToken" from the header to "FinalSale" to indicate you called the pricing Api

Fieldpine applications that use the PricingAPI have this strategy:

Requesting Discounts

Discounts can be requested by adding a "Discount1Name" into the the request. The Discounts Examples has a number of examples showing discounts.

{
  "Customer": 234665,
  "Saleline": [{
    "Pid": 246,
    "Qty": 2,
    "Sequence": 1,
    "Discount1Name": "seniors"       « Apply a "Seniors" discount to this item
  }]
}

Notes and Cautions with this API

If you call this API to price a sale, you must return the "PriceToken" in the response when creating the sale. This provides the proof for support in case of errors.

In many countries, you must honour the price displayed to the customer.

This API is only able to price sales as of now. It cannot price in the future or historically.

Pricing is time sensitive. If there is a significant lag between calling the Pricing API and completing the sale, prices may change

If you price a sale with the Pricing API, you must pass the total price for each item in the sale when you finally save it. You can not use "calculate" as a price, as the calculation has already been done, and presumably this price given to the customer.

Handling Errors and Warnings

As part of the pricing process, the sale details provided are checked for some business rules and issues returned in the pricing response. You are free to use or ignore these errors as you see fit.

Sales Errors are returned in TWO places, in the actual object where it relates too, and also as an array of all errors.

Consider this simple request which includes an unknown Discount Name

{
  "Saleline_Create": [{
    "Pid": 12345,
    "Qty": 1,
    "Sequence": 1,
    "Discount1Name": "August Special"       « Incorrect Name
  }]
}

The response from the Pricing API will be

{
  "data": {
    "Sale_Create": [
      {
        "PriceToken": "KEPZFLEAZZRE897FAMR5QPAAAABQAAAB",
        "Sale_Errors": [
          {
            "Comments": "Unknown Discount Name"
          }
        ],
        "Saleline_Create": [
          {
            "Pid": 12345,
            "Qty": 1,
            "TotalPrice": "298.000000",
            "Sale_Errors": [
              {
                "Comments": "Unknown Discount Name"
              }
            ],
            "Sale_PricingInfo": [
              {
                "CopyField": "TotalPrice",
                "PriceTrace": "TicketPrice=149.0000"
              }
            ]
          }
        ]
      }
    ]
  }
}

If your request has multiple errors, such as this one

{
  "Saleline_Create": [{
    "Pid": 0,                               « Invalid Product
    "Qty": 1,
    "Sequence": 1,
    "Discount1Name": "August Special"       « Incorrect Name
  }]
}

Then the response may include multiple errors as shown.

{
  "data": {
    "Sale_Create": [
      {
        "PriceToken": "KEPZFLEAZZRE897FAQ9PQPAAAACAAAAB",
        "Sale_Errors": [
          {
            "Comments": "Unknown product"
          },
          {
            "Comments": "Unknown Discount Name"
          }
        ],
        "Saleline_Create": [
          {
            "Pid": 0,
            "Qty": 1,
            "TotalPrice": "0.000000",
            "Sale_Errors": [
              {
                "Comments": "Unknown product"
              },
              {
                "Comments": "Unknown Discount Name"
              }
            ],
            "Sale_PricingInfo": [
              {
                "CopyField": "TotalPrice",
                "PriceTrace": "TicketPrice=0.0000"
              }
            ]
          }
        ]
      }
    ]
  }
}

Consider the purchase of Whiskey which may require age verification

    {
        "LINE": [{
                "Pid": 12345,
                "Description": "Whiskey, 1L",
                "Qty": 1,
                "Sequence": 1
            }]
    }
    

The pricing response might be

    {
        "LINE": [{
                "Pid": 12345,
                "Description": "Whiskey, 1L",
                "Qty": 1,
                "Sequence": 1,
                "TotalPrice": 38.50,
                "UnitPrice": 38.50,
                "Sale_Errors": [
                    { "Comments": "Verify 18+ to purchase this item",
                      "ErrorCode": 8203,
                      "Severity": 1,
                      "SeverityText": "legal",
                      "SaleLineSeq": 1
                    }
                ],
                "Sale_PricingInfo": [
                    { 
                        "CopyField": ['UnitPrice', 'TotalPrice']
                    }
                ]
            }],
            "Sale_Errors": [
                { "Comments": "Verify 18+ to purchase this item",
                    "ErrorCode": 8203,
                    "Severity": 1,
                    "SeverityText": "legal",
                    "SaleLineSeq": 1
                }
            ]
    }
    

Not all items returned in Sale_Errors are strictly errors. The severity field returns details of what the server considers as per this table

SeveritySeverityTextComments
1legalA warning about a condition that is a legal requirement.
2stopDo not proceed with this, the server will not accept it. Very rare.
3invalidSomething is wrong with the sale as given so far. If might be rejected when saved.
For example, you have not yet set the customer and a business rule exists requiring customers on all sales
4warningSomething more minor is potentially wrong with the sale
5infoThings you might like to know while processing the sale

If the store has a special this month, of spend $50 or more and get $5 off, then the pricing response may change to include this. Note how the upsell instruction is only present in ONE Sale_Errors, not TWO, as it does not specifically relate to a Saleline.

    {
        "LINE": [{
                "Pid": 12345,
                "Description": "Whiskey, 1L",
                "Qty": 1,
                "Sequence": 1,
                "TotalPrice": 38.50,
                "UnitPrice": 38.50,
                "Sale_Errors": [
                    { "Comments": "Verify 18+ to purchase this item",
                      "ErrorCode": 8203,
                      "Severity": 1,
                      "SeverityText": "legal",
                      "SaleLineSeq": 1
                    }
                ]
            }],
            "Sale_Errors": [
                { "Comments": "Verify 18+ to purchase this item",
                    "ErrorCode": 8203,
                    "Severity": 1,
                    "SeverityText": "legal",
                    "SaleLineSeq": 1
                },
            { "Comments": "Spend $50 this month and get $5 off",
            "ErrorCode": 20000,
            "Severity": 5,
            "SeverityText": "info"
                }

            ]
    }