Basket lock
Some purchase workflows require a (short term) lock on a shopping basket to make sure there are no modifications concurrent with the payment. For these scenarios it is possible to configure a lock request which will take place shortly before the actual purchase:
Request
In this case OpenApp will execute a HTTP POST to the to the endpoint configured in the control panel for a recalculate, with an updated basket in the request body:
POST <recalculate-url>?lock=true
So if you configured the value https://shop.example.com/api/openapp/basket, the request executed by OpenApp will be:
POST https://shop.example.com/api/openapp/basket?lock=true
The request body contains the basket from the user. For example:
- Request
- Schema
{
"requestId": "request-id",
"id": "basket-id",
"price": {
"currency": "PLN",
"discounts": [
{
"code": "new-discount-code-text"
}
]
},
"products": [
{
"ean": "12312",
"id": "id123",
"quantity": 3
}
],
"loggedUser": "user-id-from-webshop"
}
requestIdstringRequiredThe ID of the request as generated by OpenApp.
maxLength: 36
idstringOptionalA null value for the basket id indicates that this is a request to create a new basket for a repurchase.
maxLength: 36
priceobjectRequiredShow child parametersHide child parameters2
currencystringRequiredThe currency
discountsarray of RecalculateDiscountRequiredDiscounts to apply in price calculation.
Show child parametersHide child parameters1
codestringRequiredThe discount code.
maxLength: 36
productsarray of RecalculateProductRequiredShow child parametersHide child parameters3
eanstringOptionalThe ean (or other barcode on the product). Specifying this allows the user to search in his order history by scanning the barcode to do a re-purchase.
maxLength: 36
idstringRequiredThe unique ID of the product.
maxLength: 36
quantitynumberRequiredThe requested quantity
loggedUserstringOptionalRaw JSON Schema
{
"description": "Basket recalculate request",
"additionalProperties": false,
"type": "object",
"properties": {
"requestId": {
"description": "The ID of the request as generated by OpenApp.",
"maxLength": 36,
"type": "string",
"title": "requestId"
},
"id": {
"description": "A null value for the basket id indicates that this is a request to create a new basket for a repurchase.",
"maxLength": 36,
"type": "string",
"title": "id"
},
"price": {
"$ref": "#/definitions/RecalculatePrice",
"title": "price"
},
"products": {
"type": "array",
"items": {
"$ref": "#/definitions/RecalculateProduct"
},
"title": "products"
},
"loggedUser": {
"type": "string",
"title": "loggedUser"
}
},
"required": [
"price",
"products",
"requestId"
],
"definitions": {
"RecalculatePrice": {
"title": "RecalculatePrice",
"type": "object",
"properties": {
"currency": {
"description": "The currency",
"type": "string",
"title": "currency"
},
"discounts": {
"description": "Discounts to apply in price calculation.",
"type": "array",
"items": {
"$ref": "#/definitions/RecalculateDiscount"
},
"title": "discounts"
}
},
"required": [
"currency",
"discounts"
]
},
"RecalculateDiscount": {
"title": "RecalculateDiscount",
"type": "object",
"properties": {
"code": {
"description": "The discount code.",
"maxLength": 36,
"type": "string",
"title": "code"
}
},
"required": [
"code"
]
},
"RecalculateProduct": {
"title": "RecalculateProduct",
"type": "object",
"properties": {
"ean": {
"description": "The ean (or other barcode on the product). Specifying this allows the user to search in his order history by scanning the barcode to do a re-purchase.",
"maxLength": 36,
"type": "string",
"title": "ean"
},
"id": {
"description": "The unique ID of the product.",
"maxLength": 36,
"type": "string",
"title": "id"
},
"quantity": {
"description": "The requested quantity",
"type": "number",
"title": "quantity"
}
},
"required": [
"id",
"quantity"
]
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}
Response
In response, the website should send the basket content and configured delivery options in the same format as for the retrieve basket response. The expiresAt property indicates until which time the basket is valid and locked.
This is shown in the example below:
- Response
- Schema
{
"id": "basket-id",
"expiresAt": "2022-03-23T21:00:00Z",
"price": {
"currency": "PLN",
"discounts": [
{
"code": "discount-code-text",
"value": 1000
}
],
"basketValue": 13000
},
"deliveryOptions": [
{
"key": "INPOST_APM",
"cost": 0
},
{
"key": "DPD_COURIER",
"cost": 1000,
"timing": "next business day"
}
],
"products": [
{
"ean": "12312",
"id": "id123",
"name": "Superb product",
"images": [
"http://cdn.merchant.com/static/products/id123/1",
"http://cdn.merchant.com/static/products/id123/2"
],
"quantity": 2,
"unitPrice": 7000,
"linePrice": 14000,
"originalUnitPrice": 7000,
"originalLinePrice": 14000,
"policies": [
{
"type": "AGE",
"criteria": {
"minAge": 18
}
}
]
}
],
"loggedUser": "user-id-from-webshop"
}
idstringRequiredThe unique ID of the basket.
maxLength: 36
requestIdstringOptionalThe ID of the basket request as generated by OpenApp. Mandatory in case of an asynchronous connection through a queue in order to correlate the placed order with the response.
maxLength: 36
expiresAtstringRequiredThe moment until which the basket is valid. This can be used to indicate a basket needs to be ordered before a specific time in order to guarantee availability.
format: date-time
oaOrderIdstringOptionalThe OpenApp order ID (if known).
priceobjectRequiredShow child parametersHide child parameters3
currencystringRequiredbasketValueintegerRequiredThe price of the basket. Price is expressed as the number (integer) of 1/100s of the price.
minimum: 0
discountsarray of BasketPriceDiscountRequiredApplied discounts
Show child parametersHide child parameters3
codestringRequiredThe discount code.
maxLength: 36
valueintegerRequiredThe value of the discount. Value is expressed as the number (integer) of 1/100s of the currency.
minimum: 0
errorenumOptionalThe error code of the discount
Possible values: EXPIREDINVALIDNOT_APPLICABLEUSED
deliveryOptionsarray of BasketDeliveryOptionRequiredShow child parametersHide child parameters3
keyenumRequiredPossible values: DHL_COURIERDHL_PICKUPDPD_COURIERDPD_PICKUPELECTRONICFEDEX_COURIERGEIS_COURIERGLS_COURIERINPOST_APMINPOST_COURIERINSTORE_PICKUPORLEN_APMPOCZTA_POLSKA_APMPOCZTEX_COURIERUPS_COURIER
costintegerRequiredThe price of the delivery. Price is expressed as the number (integer) of 1/100s of the price.
timingstringOptionalThe estimation of the delivery time, i.e. 'next business day' or 'July 18th'.
maxLength: 40
productsarray of BasketProductRequiredShow child parametersHide child parameters11
namestringRequiredThe product name.
imagesarray of stringRequiredThe URLs of the product image
originalUnitPriceintegerRequiredThe original (before discount) price of a single product. Price is expressed as the number (integer) of 1/100s of the price.
originalLinePriceintegerRequiredThe original (before discount) price of the products. Price is expressed as the number (integer) of 1/100s of the price.
errorenumOptionalError code when the product request can not be accomodated in a recalculate request.
Possible values: OUT_OF_STOCKQUANTITY_TOO_BIG
eanstringOptionalThe ean (or other barcode on the product). Specifying this allows the user to search in his order history by scanning the barcode to do a re-purchase.
maxLength: 36
idstringRequiredThe unique ID of the product.
maxLength: 36
quantityintegerRequiredThe number of items in the purchase.
minimum: 0
unitPriceintegerRequiredThe price of a single product. Price is expressed as the number (integer) of 1/100s of the price.
linePriceintegerRequiredThe price of the products. Price is expressed as the number (integer) of 1/100s of the price.
policiesarray of ProductPolicyOptionalThe list of policies applied to the product.
maxItems: 1
Show child parametersHide child parameters2
typeenumRequiredPossible values: AGE
criteriaobjectRequiredShow child parametersHide child parameters1
minAgeintegerRequiredminimum: 0
invoiceAddressMandatorybooleanOptionalWhether an invoice address is mandatory
loggedUserstringOptionalThe unique ID of the user.
maxLength: 255
Raw JSON Schema
{
"description": "Basket returned on retrieval or recalculation",
"additionalProperties": false,
"type": "object",
"properties": {
"id": {
"description": "The unique ID of the basket.",
"maxLength": 36,
"type": "string",
"title": "id"
},
"requestId": {
"description": "The ID of the basket request as generated by OpenApp. Mandatory in case of an asynchronous connection through a queue in order to correlate the placed order with the response.",
"maxLength": 36,
"type": "string",
"title": "requestId"
},
"expiresAt": {
"description": "The moment until which the basket is valid. This can be used to indicate a basket needs to be ordered before a specific time in order to guarantee availability.",
"format": "date-time",
"type": "string",
"title": "expiresAt"
},
"oaOrderId": {
"description": "The OpenApp order ID (if known).",
"type": "string",
"title": "oaOrderId"
},
"price": {
"$ref": "#/definitions/BasketPrice",
"title": "price"
},
"deliveryOptions": {
"type": "array",
"items": {
"$ref": "#/definitions/BasketDeliveryOption"
},
"title": "deliveryOptions"
},
"products": {
"type": "array",
"items": {
"$ref": "#/definitions/BasketProduct"
},
"title": "products"
},
"invoiceAddressMandatory": {
"description": "Whether an invoice address is mandatory",
"type": "boolean",
"title": "invoiceAddressMandatory"
},
"loggedUser": {
"description": "The unique ID of the user.",
"maxLength": 255,
"type": "string",
"title": "loggedUser"
}
},
"required": [
"deliveryOptions",
"expiresAt",
"id",
"price",
"products"
],
"definitions": {
"BasketPrice": {
"title": "BasketPrice",
"type": "object",
"properties": {
"currency": {
"type": "string",
"title": "currency"
},
"basketValue": {
"description": "The price of the basket. Price is expressed as the number (integer) of 1/100s of the price.",
"minimum": 0,
"type": "integer",
"title": "basketValue"
},
"discounts": {
"description": "Applied discounts",
"type": "array",
"items": {
"$ref": "#/definitions/BasketPriceDiscount"
},
"title": "discounts"
}
},
"required": [
"basketValue",
"currency",
"discounts"
]
},
"BasketPriceDiscount": {
"title": "BasketPriceDiscount",
"type": "object",
"properties": {
"code": {
"description": "The discount code.",
"maxLength": 36,
"type": "string",
"title": "code"
},
"value": {
"description": "The value of the discount. Value is expressed as the number (integer) of 1/100s of the currency.",
"minimum": 0,
"type": "integer",
"title": "value"
},
"error": {
"description": "The error code of the discount",
"enum": [
"EXPIRED",
"INVALID",
"NOT_APPLICABLE",
"USED"
],
"type": "string",
"title": "error"
}
},
"required": [
"code",
"value"
]
},
"BasketDeliveryOption": {
"title": "BasketDeliveryOption",
"type": "object",
"properties": {
"key": {
"$ref": "#/definitions/MerchantDeliveryOptions",
"title": "key"
},
"cost": {
"description": "The price of the delivery. Price is expressed as the number (integer) of 1/100s of the price.",
"type": "integer",
"title": "cost"
},
"timing": {
"description": "The estimation of the delivery time, i.e. 'next business day' or 'July 18th'.",
"maxLength": 40,
"type": "string",
"title": "timing"
}
},
"required": [
"cost",
"key"
]
},
"MerchantDeliveryOptions": {
"title": "MerchantDeliveryOptions",
"enum": [
"DHL_COURIER",
"DHL_PICKUP",
"DPD_COURIER",
"DPD_PICKUP",
"ELECTRONIC",
"FEDEX_COURIER",
"GEIS_COURIER",
"GLS_COURIER",
"INPOST_APM",
"INPOST_COURIER",
"INSTORE_PICKUP",
"ORLEN_APM",
"POCZTA_POLSKA_APM",
"POCZTEX_COURIER",
"UPS_COURIER"
],
"type": "string"
},
"BasketProduct": {
"title": "BasketProduct",
"type": "object",
"properties": {
"name": {
"description": "The product name.",
"type": "string",
"title": "name"
},
"images": {
"description": "The URLs of the product image",
"type": "array",
"items": {
"type": "string"
},
"title": "images"
},
"originalUnitPrice": {
"description": "The original (before discount) price of a single product. Price is expressed as the number (integer) of 1/100s of the price.",
"type": "integer",
"title": "originalUnitPrice"
},
"originalLinePrice": {
"description": "The original (before discount) price of the products. Price is expressed as the number (integer) of 1/100s of the price.",
"type": "integer",
"title": "originalLinePrice"
},
"error": {
"description": "Error code when the product request can not be accomodated in a recalculate request.",
"enum": [
"OUT_OF_STOCK",
"QUANTITY_TOO_BIG"
],
"type": "string",
"title": "error"
},
"ean": {
"description": "The ean (or other barcode on the product). Specifying this allows the user to search in his order history by scanning the barcode to do a re-purchase.",
"maxLength": 36,
"type": "string",
"title": "ean"
},
"id": {
"description": "The unique ID of the product.",
"maxLength": 36,
"type": "string",
"title": "id"
},
"quantity": {
"description": "The number of items in the purchase.",
"minimum": 0,
"type": "integer",
"title": "quantity"
},
"unitPrice": {
"description": "The price of a single product. Price is expressed as the number (integer) of 1/100s of the price.",
"type": "integer",
"title": "unitPrice"
},
"linePrice": {
"description": "The price of the products. Price is expressed as the number (integer) of 1/100s of the price.",
"type": "integer",
"title": "linePrice"
},
"policies": {
"description": "The list of policies applied to the product.",
"maxItems": 1,
"type": "array",
"items": {
"$ref": "#/definitions/ProductPolicy"
},
"title": "policies"
}
},
"required": [
"id",
"images",
"linePrice",
"name",
"originalLinePrice",
"originalUnitPrice",
"quantity",
"unitPrice"
]
},
"ProductPolicy": {
"title": "ProductPolicy",
"type": "object",
"properties": {
"type": {
"$ref": "#/definitions/ProductPolicyType",
"title": "type"
},
"criteria": {
"$ref": "#/definitions/AgeCriteria",
"title": "criteria"
}
},
"required": [
"criteria",
"type"
]
},
"ProductPolicyType": {
"title": "ProductPolicyType",
"enum": [
"AGE"
],
"type": "string"
},
"AgeCriteria": {
"title": "AgeCriteria",
"type": "object",
"properties": {
"minAge": {
"type": "integer",
"minimum": 0,
"title": "minAge"
}
},
"required": [
"minAge"
]
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}
Of course it is possible that the website cannot accomodate the requested basket, for instance because not enough stock is available or prices changed. In that scenario the website should repond with the part of the basket that is available, plus an error code to indicate any errors in the basket. OpenApp will prompt the user to decide whether he wants to continue the purchase.
This example is an example of a simple basket. For a complete description of the basket response see the Schema tab above.