Document Tree
Document Properties
Kbid
30Z982
Last Modified
29-Aug-2023
Added to KB
29-Aug-2023
Public Access
Everyone
Status
Online
Doc Type
Concepts
Product
  • ICM 11
  • ICM 12
Concept - Basket REST API (v1)

Introduction

The intention of this document is to explain some dynamic aspects of the basket and checkout REST API that are not covered by the REST API reference.

Glossary

TermDescription
payment methodConfigured instance of a payment connector implementation to a specific provider. Also known as payment service.
payment instrumentA saved set of data for a payment service at a basket.
paymentPayment instrument set at the basket to pay with.

References

Basket Resource

General

Basic Architecture

Versioning

A new version of the Basket REST API had to be created since the new version (v1) is incompatible with the previous (legacy) Basket REST interface for all requests. Hence, media-type-based versioning has been introduced to distinguish between legacy- and v1-related REST requests. A REST client must set the following HTTP Accept header in case of v1 requests:

HTTP Accept Header for V1 requests of Basket REST API
Accept: application/vnd.intershop.basket.v1+json

In contrast, the standard media type header for JSON-based requests must be used to target requests of legacy Basket REST API:

HTTP Accept Header for legacy requests of Basket REST API
Accept: application/json

This way requests of the legacy and v1 Basket REST API can be used side by side by a REST client at the same time.

Class Hierarchy

The resource implementation is the main entry point for requests in the Basket REST API. The following diagram shows the class hierarchy of Basket REST API related classes:

The resource class for requests of the legacy Basket REST API inherits from V1-item resource implementation to ensure that legacy and V1 requests can be used side by side.

Resource class implementation of the legacy Basket REST API (blue) contains much functionality for request processing, like determining the current user's basket or triggering basket calculation, etc. In contrast, v1-related resource classes (green) are quite simple:

  • v1 Basket REST API provides two different resource class implementations for the basket's list and entity resources.
  • Both resource class implementations are quite simple and mainly include annotations for Swagger API documentation and simple calls of the request classes' invoke-method.
  • Request class implementations

This way, the functionality for different requests is clearly separated instead of scattered over a single resource class implementation as done in the implementation of the legacy basket REST API. All request class implementations use a basket handler class that works on top of the Business Objects (BO)-layer. This means that no pipelines are called by the handler implementation except the ProcessBasket-Calculate pipeline.

Note

Custom pipelines, triggered by pipeline extension points of other sub-pipelines of ProcessBasket are not called by the v1 Basket REST functionality at all.

Transaction Handling

Method implementations of REST requests processing database updates must be annotated with the com.intershop.component.rest.capi.transaction.Transactional annotation. This annotation provides automatic transaction support for committing database changes after completion of request processing.

If request processing fails for any reason, e.g., in the handler class, the transaction can be rolled back as shown below:

Mark transaction as rollback only
// trigger roll back in case of an error
if (result.isError())
{
    Transaction tx = transactionMgr.getCurrentTransaction();
    tx.markRollbackOnly();
}

Error Handling

Error handling exclusively based on HTTP status codes is not sufficient for the majority of the REST clients. Therefore the v1 Basket REST API introduces a unique handling for errors as well as other information to provide a REST client with as much information as possible about the results of processing a specific request.

...
    "errors": [
        {
            "causes": [
                {
                    "code": "basket.address.create_address_duplicate_address.error",
                    "message": "An address with this data already exists."
                }
            ],
            "code": "basket.address.creation.error",
            "message": "The address could not be added to your basket.",
            "status": "422"
        }],
    "infos": [
        {
            "code": "basket.validation.shipping_method_was_set.info",
            "message": "The selected shipping method is not valid anymore. A new shipping method has been selected for the basket."
        }]
...

Besides the data section containing the response's payload data, a response might contain an errors and an infos section that can include one or multiple entries. These sections contain at least a unique key for the error or the info and a localized message describing the issue or info. The locale of the message follows the one specified in the request URL. Furthermore, there is a fallback to the standard locale if no localization is found for the request locale. Additionally, an info or error message may contain an embedded cause element. A cause element has the same structure as its surrounding error or info entry and provides further information to isolate the issue.

An entry of the infos or errors section may contain additional parameters if these help to further describe the issue. Furthermore, an infos or errors section may contain a paths attribute whose value points to the origin of the error or info in the request's JSON payload. The syntax of the path corresponds to the JSON Path DSL.

Info message with parameters and path attributes
...
    "infos": [
        {
            "causes": [
                {
                    "code": "basket.line_item.add_item_added_to_new_line_item_with_adjusted_quantity.info",
                    "message": "This product has limited inventory. We have adjusted the quantity to reflect the number of products we have available and added the product to your cart.",
                    "parameters": {
                        "requested": "110",
                        "granted": "100"
                    },
                    "paths": [
                        "$[0].quantity"
                    ]
                },
                {
                    "code": "basket.line_item.add_item_max_item_quantity_exceeded.info",
                    "message": "The quantity you entered is invalid. We have adjusted the quantity to meet our Maximum Purchasing Policy."
                }
            ],
            "code": "basket.line_item.creation.info",
            "message": "This product has been added to your basket.",
            "paths": [
                "$[0]"
            ],
            "status": "201"
        }
    ],
...

See Concept - REST API Error and Info Messages (v1) for details regarding the errors  and infos sections.

Basket Calculation

In general, every changing request (POST, PUT, PATCH, DELETE) that manipulates the basket's resource or one of its sub-resources may affect results of the previous basket calculation by invalidating these results. This way the basket has to be re-calculated after a single or several changing REST requests to get valid amounts for prices and costs again. There are two basic use cases:

  1. Every basket manipulation operation, like adding a new item to the basket, should trigger a basket (re-)calculation, so that the REST client can always be sure that the server provides a basket with correct calculation results.
  2. Several basket manipulation operations should be processed by the client without triggering a basket (re-)calculation after each request. An example might be adding various items - for any reason - by single requests to the basket. A (re-)calculation after each request might neither be necessary nor desired due to performance issues.

For this reason the responsibility for basket calculation is handed over to the REST client in the new basket and the checkout REST API. A REST client can control the basket calculation behavior with the calculated attribute that is available at the following item resources and sub-resources:

  • basket
  • item
  • shipping bucket

whereas

  • calculated=false means that no calculation should be triggered by the server,
  • calculated=true means that (re-)calculation should be triggered by the server. This is the default if neither is specified.

If the client is not certain about the calculation state of the basket, it can trigger the following request:

Request: PATCH /baskets/<basket_id>
{
	"calculated": true
}

There is no performance impact in this case since a basket with a valid calculation state will not be (re-)calculated as a result of this request.

Basket Purchase Currency

Basket's purchase currency, i.e. the currency the basket is calculated with, is controlled by the optional cur REST request matrix parameter only:

Parameter for basket's purchase currency
https://.../-;loc=en_US;cur=USD/baskets/...

The purchaseCurrency attribute of the basket item resource is read-only and informative only, means setting the value of this attribute in the context of POST/PUT/PATCH requests has no effect to basket calculation at all.

GET requests to a basket item resource ignore the value of the cur matrix parameter completely. This way, a GET request with the cur matrix parameter value EUR is answered with the value USD for the purchaseCurrency attribute if the basket is currently calculated with the purchase currency USD. Furthermore there is an info message that basket's purchase currency differs from requested currency.

GET .../-;cur=EUR/baskets/<basket-id>
{
    "data" : {
        ...
        "purchaseCurrency": "USD",
        ...
    }
    "infos": [
        {
            "code": "request.parameter.currency.differs_from_basket_purchase_currency.",
            "message": "Basket purchase currency differs from requested currency specified for the 'cur' matrix parameter. All money values are returned in basket's purchase currency."
        }
    ]
}

However, the REST interface does not respond with an error in this case. A client has to note this behavior to avoid confusion related to basket's purchase currency.


In case that a REST client demands for changing basket's purchase currency without changing the basket otherwise, it must send a PATCH request with the new currency and at least the calculated attribute with a value equal to true:

PATCH .../-;cur=EUR/baskets/<basket-id>
{
    "calculated": true
}

The request explicitly forces invalidation of basket calculation and a subsequent re-calculation. This behavior works for all subresources of the basket item resource that contain the calculated attribute. This way, the purchase currency can be changed implicitly with every request that manipulates the basket in any way (including the calculated attribute with a value equal to true) or explicitly by sending a PATCH  request that only contains the calculated attribute with a value  equal to true.

Basket Validation

A validation's subresource has been introduced for the basket item resource to give a REST client the possibility to validate all or several basket settings for correctness.

Request: POST /baskets/<basket_id>/validations
{
	"scopes": ["All"],
	"adjustmentsAllowed": false,
	"errorBehavior": "NeverStop"
}

Validations could not be processed in the course of the basket's PATCH request, as done for basket calculation. The reason for this is that the payload of the PATCH request's response would be mixed with payload origin from basket validation, especially in the errors and infos section. Furthermore, a client was not able to differentiate whether a returned HTTP error status is issued by PATCH request processing or by validation errors.

See Concept - Basket Handling: Validate Basket for details regarding validation scopes, allowance for adjustments and error behavior.

This way the POST request to the basket's validations subresource responds with a data section that contains, besides requested validation parameters, error and info messages resulting from validation processing.

Response: POST /baskets/<basket_id>/validations
{
    "data": {
        "adjustmentsAllowed": false,
        "basket": "L9kKAEsBWAgAAAFuARZXSAMd",
        "errorBehavior": "NeverStop",
        "results": {
            "adjusted": false,
            "errors": [
                {
                    "code": "basket.validation.payment_missing.error",
                    "message": "No payment method has been selected.",
                    "parameters": {
                        "scopes": "Payment"
                    },
                    "paths": [
                        "$.payments"
                    ]
                },
                {
                    "code": "basket.validation.basket_not_covered.error",
                    "message": "The value of the basket is not covered by the selected payment instruments.",
                    "parameters": {
                        "scopes": "Payment"
                    },
                    "paths": [
                        "$.payments"
                    ]
                },
                {
                    "code": "basket.validation.invoice_to_address_missing.error",
                    "message": "No invoice-to address has been selected.",
                    "parameters": {
                        "scopes": "InvoiceAddress,Addresses"
                    },
                    "paths": [
                        "$.invoiceToAddress"
                    ]
                }
            ],
            "valid": false
        },
        "scopes": [
            "All"
        ]
    }
}

Extensibility

There are several concepts to extend the basket REST API v1.

Attribute Subresource

The extension concept of Attribute Subresource is available for REST resources and subresources that represent custom attributes of a business object, which has a com.intershop.beehive.core.capi.domain.ExtensibleObjectPO representation. The reason for this limitation is that these business objects can store the values provided to an attribute subresource by a REST client in their Attribute Value (AV) tables in the database.

In the Basket REST API v1 the following resources and sub-resources support this extension mechanism:

  • basket
  • line item
  • address

One advantage of the extensibility via Attribute Subresource is the fact that this mechanism allows extensibility while retaining the type of additional data. As these attributes are stored as custom attributes in ICM's AV database tables, all data types are supported that can be stored there:

  • boolean
  • date
  • decimal
  • double
  • integer
  • long
  • money
  • quantity
  • string
  • text
  • multiple boolean
  • multiple date
  • multiple decimal
  • multiple double
  • multiple integer
  • multiple long
  • multiple string
Implementation

An attributes sub-resource is introduced for every resource/subresource that supports this extension concept. This way additional data of different types can simply be provided and retrieved in the REST API.

Request: POST /baskets/<basket_id>/attributes
{
	"name": "testDate",
	"type": "Date",
	"value": "2019-01-31T18:23:00+02:00"
}
Response: POST /baskets/<basket_id>/attributes
{
    "data": {
        "name": "testDate",
        "type": "Date",
        "value": "2019-01-31T18:23:00+02:00"
    },
    "links": {
        "self": "http://localhost/INTERSHOP/rest/WFS/inSPIRED-inTRONICS-Site/-;loc=en_US&cur=USD/baskets/3hcKAEsBBxoAAAFt0A4aeEja/attributes/testDate"
    }
}

Another advantage of this extension mechanism is that no implementation is required at all. REST handler and object mapper of attributes subresource handles storage of attribute data behind the scenes.

Customizable Requests and Responses

Customizable Requests and Responses of REST requests and responses is available for REST resources and subresources that mainly represent domain objects, like basket, basket totals, discounts, etc. . The extension concept of Customizable Requests and Responses differs from Attribute Subresources in the following points:

  • Up to ICM 7.10.26, only values of type String  were supported. Starting with ICM 7.10.27, the value type is now Object.
  • Programming effort is necessary by adding extension classes of REST handler and object mapper(s).

This extension mechanism is mainly based on the concepts of:

  • com.fasterxml.jackson.annotation.JsonAnyGetter
  • com.fasterxml.jackson.annotation.JsonAnySetter

which allow to specify additional fields in the REST request's and the response's JSON body.

Request

The following JSON snippet of updating a basket contains the two regular fields commonShipToAddress and commonShippingMethod . Furthermore, JSON content contains the fields string, integer and custom that are not part of the Basket REST API. Since these fields cannot be assigned to regular attributes of the corresponding Java resource object class that represents the basket item resource during JSON unmarshalling, they are put in a map.

POST /baskets/<basket_id>
{
	"commonShipToAddress": "urn:address:customer:7aEKAEsBn7EAAAFsnihVfB17:cWMKAEsBn7UAAAFsnihVfB17",
    "commonShippingMethod": "STD_GROUND",
    "string" : "foo",
    "integer" : 42,
	"custom" : {
		"custom_string" : "bar",
		"custom_integer" : 42
	}
}

Afterwards the map entries can be retrieved from the basket resource object (com.intershop.sellside.rest.basket.v1.capi.resourceobject.basket.BasketRO). The prerequisite for this is that the related resource object extends the class com.intershop.sellside.rest.common.v1.capi.resourceobject.common.CustomizableRO with its method:

+getAnyFields(): Map<String,Object>

Note

All field values are of type Object and are not automatically converted. Type casting and conversion must be done manually instead.

Customizablity of REST client requests, however, does not only affect the Resource Objects (RO). Data provided with ROs have to be set on ICM's Business Objects (BO) in any way. For this reason several REST handler implementations call registered implementations of the interface ObjectHandlerExtension<S,T> .

ObjectHandlerExtension<S,T>
public interface ObjectHandlerExtension<S, T>
{
    /**
     * Checks if this extension is applicable for the current context. If other context objects
     * (e.g. ApplicationBO) are required for deciding if the handler has to be executed, it has to be injected.
     * 
     * @param source The source object handed in within the request.
     * @param target The business object to be updated.
     * @return <code>true</code> is the extension is applicable for the given context, otherwise <code>false</code>.
     */
    default boolean isApplicable(S source, T target)
    {
        return true;
    }
    
    /**
     * Updates the given target with the data specified in the source.
     * 
     * @param source
     *            The data object to get data from.
     * @param target
     *            The target object that should be updated.
     * @param result
     *            The result to record feedback data representing the current status of an update 
     *            handler execution as well as collecting all error and info messages.
     */
    void update(S source, T target, MethodInvocationResult<T> result);
}

The following example shows how custom data provided with a request to the baskets item resource can be processed in the REST framework of the server:

REST Handler Extensions
// Basket handler implementation calls registered custom handlers

public class BasketHandlerImpl implements BasketHandler
{
    @Inject
    private Set<ObjectHandlerExtension<BasketRO, BasketBO>> handlers;

    ...

    private void invokeExtendedBasketUpdateHandlers(BasketRO basketRO, BasketBO basketBO,
                    MethodInvocationResult<BasketBO> result)
    {
        handlers.stream().filter(h -> h.isApplicable(basketRO, basketBO))
                        .forEach(h -> h.update(basketRO, basketBO, result));
    }

    ...
}

// Custom basket REST handler can do its own processing of data provided in request body's custom fields.

public class MyCustomBasketDataHandler implements ObjectHandlerExtension<BasketRO, BasketBO>
{
    @Override
    public boolean isApplicable(BasketRO basketRO, BasketBO basketBO)
    {
        // Decide if there are any further conditions, whether the update method should be called or not!
    }

    @Override
    public void update(BasketRO basketRO, BasketBO basketBO, MethodInvocationResult<BasketBO> result)
    {
        Map<String, Object> myCustomData = basketRO.getAnyFields();
        // e.g. cast/convert and process/set value of an above's map entry on your own BasketBOExtension implementation
    }    
}

// Guice registration of the REST handler extension.

public class MyHandlerModule extends AbstractModule
{
    @Override
    protected void configure()
    {
        Multibinder<ObjectHandlerExtension<BasketRO, BasketBO>> enhanceBasketHandlers = Multibinder
                        .newSetBinder(binder(), new TypeLiteral<ObjectHandlerExtension<BasketRO, BasketBO>>() {});
        enhanceBasketHandlers.addBinding().to(MyCustomBasketDataHandler.class);
    }
}

The following handler implementations call handler extensions by default:

  • com.intershop.sellside.rest.basket.v1.internal.handler.AddressHandlerImpl 
  • com.intershop.sellside.rest.basket.v1.internal.handler.BasketHandlerImpl 
  • com.intershop.sellside.rest.basket.v1.internal.handler.LineItemHandlerImpl 
  • com.intershop.sellside.rest.basket.v1.internal.handler.ShippingHandlerImpl
  • com.intershop.sellside.rest.order.v1.internal.handler.OrderHandlerImpl
Response

The following JSON snippet of getting a basket resource contains the fields string, integer and custom in the response body's data section that are not part of the Basket REST API:

GET /baskets/<basket_id>
{
    "data": {
            "buckets": [
                "1648241666"
            ],
            "calculated": true,
            "commonShipToAddress": "urn:address:customer:7aEKAEsBn7EAAAFsnihVfB17:cWMKAEsBn7UAAAFsnihVfB17",
            "commonShippingMethod": "STD_GROUND",
            "customer": "Patricia",
            ...
            "string" : "foo",
            "integer" : "42",
			"custom" : {
				"custom_string" : "bar",
				"custom_integer" : 42
			}
            ...
   }
}

The prerequisite for this is that the related resource object extends the class com.intershop.sellside.rest.common.v1.capi.resourceobject.common.CustomizableRO :

+setAnyFields(String fieldName, Object fieldValue): void

Customizablity of REST client responses, however, does not only affect the Resource Objects (RO), but also custom data that have to be mapped to responses RO(s). For this reason several REST object mappers extend the abstract class ExtensibleFunction<S,T> that calls registered implementations of the interface FunctionExtension<S,T> .

ExtensibleFunction<S, T>
/**
 * Base class for all mappings based on a {@link Function} which need to be extensible.
 * 
 * For instance the basket resource object is completed with B2C data by default, but in B2B context additional data are
 * set too.
 */
@Beta
public abstract class ExtensibleFunction<S, T> implements Function<S, T>
{
    @Inject
    private Set<FunctionExtension<S, T>> extensions;

    @Override
    public T apply(S source)
    {
        T target = createTarget(source);
        target = applyExtensions(source, target);
        return target;
    }

    /**
     * Creates the initial target object and fills in the first data.
     *
     * @param source
     *            The source object to create and fill a new target object for.
     * @return The fresh and enriched target object. Must not be <code>null</code>.
     */
    protected abstract T createTarget(S source);

    /**
     * Iterates over all extension registered in the Guice module for the same source/target object combination. For all
     * applicable extensions the function is invoked.
     * 
     * @param source
     *            The source object to read the data from.
     * @param target
     *            The target object to be completed.
     */
    protected T applyExtensions(S source, T target)
    {
        Objects.requireNonNull(target);
        if (extensions != null)
        {
            for (FunctionExtension<S, T> ext : extensions)
            {
                if (ext.isApplicable(source, target))
                {
                    target = ext.apply(source, target);
                }
            }
        }
        return target;
    }
}

The following example shows how custom data can be provided with a response to a request of the baskets item resource in the REST framework of the server:

REST Object Mapper Extensions
// Custom basket resource object mapper that writes its own data to response body's custom fields.

public class CustomRO 
{
	private String custom_string;
	private Integer custom_integer;

	public CustomRO() {}

	public CustomRO(String custom_string, Integer custom_integer) 
	{
		this.custom_string = custom_string;
		this.custom_integer = custom_integer;
	}
	
	// Getter and Setter

}

@Priority(80)
public class MyCustomBasketROMapper implements FunctionExtension<BasketBO, BasketRO> 
{
    @Override
    public BasketRO apply(BasketBO source, BasketRO target)
    {
        target.setAnyField("string", "foo");
        target.setAnyField("integer", "42");

		// Object type only valid for ICM starting with 7.10.27
		target.setAnyField("custom", new CustomRO("bar", 42))

        return target;
    }
}

// Guice registration of the resource object mapper extension.

public class MyMapperModule extends AbstractModule
{
    @Override
    protected void configure()
    {
        Multibinder<FunctionExtension<BasketBO, BasketRO>> enhanceBasketMappers = Multibinder
                        .newSetBinder(binder(), new TypeLiteral<FunctionExtension<BasketBO, BasketRO>>() {});
        enhanceBasketMappers.addBinding().to(MyCustomBasketROMapper.class);
    }
}

Starting with ICM 7.10.17, FunctionExtensions are processed in the order of their @Priority annotations (beginning with the highest).

The following resource objects and their mapper implementations support mapper extensions by default:

Resource ObjectMapper Implementation
com.intershop.sellside.rest.basket.v1.capi.resourceobject.basket.BasketROcom.intershop.sellside.rest.basket.v1.internal.mapper.basket.BasketROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.basket.BasketTotalsROcom.intershop.sellside.rest.basket.v1.internal.mapper.basket.BasketTotalsROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.basket.RecurrenceROcom.intershop.sellside.rest.basket.v1.internal.mapper.basket.RecurrenceROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.lineitem.GiftMessageROcom.intershop.sellside.rest.basket.v1.internal.mapper.lineitem.GiftMessageROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.lineitem.GiftWrapROcom.intershop.sellside.rest.basket.v1.internal.mapper.lineitem.GiftWrapROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.lineitem.LineItemROcom.intershop.sellside.rest.basket.v1.internal.mapper.lineitem.LineItemROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.lineitem.LineItemPricingROcom.intershop.sellside.rest.basket.v1.internal.mapper.lineitem.LineItemPricingROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.lineitem.WarrantyROcom.intershop.sellside.rest.basket.v1.internal.mapper.lineitem.WarrantyROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.product.ProductROcom.intershop.sellside.rest.basket.v1.internal.mapper.product.ProductROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.promotion.DiscountROcom.intershop.sellside.rest.basket.v1.internal.mapper.promortion.DiscountROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.promotion.PromotionCodeROcom.intershop.sellside.rest.basket.v1.internal.mapper.promotion.PromotionCodeROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.promotion.PromotionROcom.intershop.sellside.rest.basket.v1.internal.mapper.promotion.PromotionROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.shipping.PackSlipMessageROcom.intershop.sellside.rest.basket.v1.internal.mapper.shipping.PackSlipMessageROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.shipping.ShippingBucketROcom.intershop.sellside.rest.basket.v1.internal.mapper.shipping.ShippingBucketROMapper
com.intershop.sellside.rest.basket.v1.capi.resourceobject.shipping.ShippingMethodROcom.intershop.sellside.rest.basket.v1.internal.mapper.shipping.PackMethodROMapper


Get List of Active Baskets

Response: GET /baskets
{
    "data": [
        {
            "calculated": false,
            "customer": "Patricia",
            "discounts": {},
            "id": "3hcKAEsBBxoAAAFt0A4aeEja",
            "invoiceToAddress": "urn:address:customer:7aEKAEsBn7EAAAFsnihVfB17:ljwKAEsBn7YAAAFsnihVfB17",
            "totalProductQuantity": 0,
            "totals": {
                "grandTotal": {},
                "paymentCostsTotal": {},
                "undiscountedItemTotal": {},
                "undiscountedShippingTotal": {}
            },
            "user": "patricia@test.intershop.de"
        },
        {
            "buckets": [
                "1648241666"
            ],
            "calculated": true,
            "commonShipToAddress": "urn:address:customer:7aEKAEsBn7EAAAFsnihVfB17:cWMKAEsBn7UAAAFsnihVfB17",
            "commonShippingMethod": "STD_GROUND",
            "customer": "Patricia",
            "discounts": {},
            "id": "A68KAEsBTuEAAAFt0VQaeEjX",
            "invoiceToAddress": "urn:address:customer:7aEKAEsBn7EAAAFsnihVfB17:ljwKAEsBn7YAAAFsnihVfB17",
            "lineItems": [
                "PcEKAEsBJZwAAAFtklYaeEjX"
            ],
            "purchaseCurrency": "USD",
            "totalProductQuantity": 1,
            "totals": {
                "grandTotal": {
                    "gross": {
                        "currency": "USD",
                        "value": 211.840000
                    },
                    "net": {
                        "currency": "USD",
                        "value": 178.020000
                    },
                    "tax": {
                        "currency": "USD",
                        "value": 33.82
                    }
                },
                "paymentCostsTotal": {},
                "undiscountedItemTotal": {
                    "gross": {
                        "currency": "USD",
                        "value": 208.25
                    },
                    "net": {
                        "currency": "USD",
                        "value": 175.00
                    }
                },
                "undiscountedShippingTotal": {
                    "gross": {
                        "currency": "USD",
                        "value": 3.59
                    },
                    "net": {
                        "currency": "USD",
                        "value": 3.02
                    },
                    "tax": {
                        "currency": "USD",
                        "value": 0.57
                    }
                },
                "itemTotal": {
                    "gross": {
                        "currency": "USD",
                        "value": 208.250000
                    },
                    "net": {
                        "currency": "USD",
                        "value": 175.000000
                    }
                },
                "salesTaxTotalsByTaxRate": [
                    {
                        "calculatedTax": {
                            "currency": "USD",
                            "value": 33.25
                        },
                        "effectiveTaxRate": 19.000000,
                        "taxableAmount": {
                            "currency": "USD",
                            "value": 33.25
                        }
                    }
                ],
                "shippingTaxTotalsByTaxRate": [
                    {
                        "calculatedTax": {
                            "currency": "USD",
                            "value": 0.57
                        },
                        "effectiveTaxRate": 19.000000,
                        "taxableAmount": {
                            "currency": "USD",
                            "value": 3.02
                        }
                    }
                ],
                "shippingTotal": {
                    "gross": {
                        "currency": "USD",
                        "value": 3.59
                    },
                    "net": {
                        "currency": "USD",
                        "value": 3.02
                    }
                },
                "taxTotalsByTaxRate": [
                    {
                        "calculatedTax": {
                            "currency": "USD",
                            "value": 33.82
                        },
                        "effectiveTaxRate": 19.000000,
                        "taxableAmount": {
                            "currency": "USD",
                            "value": 178.020000
                        }
                    }
                ]
            },
            "user": "patricia@test.intershop.de"
        }
    ],
    "links": {
        "self": {
            "3hcKAEsBBxoAAAFt0A4aeEja": "http://localhost/INTERSHOP/rest/WFS/inSPIRED-inTRONICS-Site/-;loc=en_US&cur=USD/baskets/3hcKAEsBBxoAAAFt0A4aeEja",
            "A68KAEsBTuEAAAFt0VQaeEjX": "http://localhost/INTERSHOP/rest/WFS/inSPIRED-inTRONICS-Site/-;loc=en_US&cur=USD/baskets/A68KAEsBTuEAAAFt0VQaeEjX"
        }
    }
}

The request returns a list of active baskets for the specified user. The following has to be considered:

  • This list contains all active baskets of the specified user, there is no separation between baskets that are created via the inSPIRED Storefront and the ones created by the REST API.
  • The entries in the list are sorted in descending order according to the basket's creation date. This means that the user's current (most recently created) basket is the first element in the list.

Delete Basket

A basket can be deleted using the following request:

Response: DELETE /baskets/<basket_id>
{
    "infos": [
        {
            "code": "basket.deletion.info",
            "message": "The basket will be deleted.",
            "status": "200"
        }
    ]
}

Note

The basket is not physically removed from the database as a result of this request, but only set to basket state INVALID. However, the basket cannot be reactivated and is not contained in the list of active baskets any longer.

Items Resource

Add Product to Basket

To add a product to the basket, use the following POST request:

Request: POST baskets/<basket_id>/items
[
	{
		"product": "5777062",
		"quantity": {
			"value": "2"
		}
	},
	{
		"product": "5920217",
		"quantity": {
			"value": "1"
		}
	}
]

This request is designed to add multiple products to the basket in one request. Adding multiple products to the basket with a single request can sometimes be a performance challenge. For example, you may want to add all the products in a wishlist or product list with a single request, rather than adding all the products with separate requests.

Get the List of Items

Response GET baskets/<basket_id>/items/<item_id>
{
    "data": {
        "basket": "K9TAqLIj1PMAAAGJYoVkDC9g",
        "calculated": true,
        "freeGift": false,
        "hiddenGift": false,
        "id": "W7HAqLIjVtUAAAGJeFVkDC9i",
        "position": 1,
        "pricing": {
            "giftingTotal": {},
            "price": {
                "gross": {
                    "currency": "USD",
                    "value": 661.64
                },
                "net": {
                    "currency": "USD",
                    "value": 556.00
                }
            },
            "salesTaxTotal": {
                "currency": "USD",
                "value": 105.64
            },
            "shippingTaxTotal": {
                "currency": "USD",
                "value": 5.29
            },
            "singleBasePrice": {
                "gross": {
                    "currency": "USD",
                    "value": 165.41
                },
                "net": {
                    "currency": "USD",
                    "value": 139.00
                }
            },
            "undiscountedPrice": {
                "gross": {
                    "currency": "USD",
                    "value": 661.64
                },
                "net": {
                    "currency": "USD",
                    "value": 556.00
                }
            },
            "undiscountedShippingTotal": {
                "gross": {
                    "currency": "USD",
                    "value": 33.15
                },
                "net": {
                    "currency": "USD",
                    "value": 27.86
                }
            },
            "undiscountedSingleBasePrice": {
                "gross": {
                    "currency": "USD",
                    "value": 165.41
                },
                "net": {
                    "currency": "USD",
                    "value": 139.00
                }
            }
        },
        "product": "5777062",
        "quantity": {
            "value": 2
        },
        "shipToAddress": "urn:address:customer:DRnAqLIjTP0AAAGIc5xXICm4:WUbAqLIjs_MAAAGIeJxXICm4",
        "shippingMethod": "STD_GROUND"
    }
}

Bulk Processing

This feature is available from ICM version 11.3.0 (Basket REST API version 1.4.0) and higher.

In the previous releases, the REST API endpoint for adding products to the basket processed additions one at a time, which could result in performance bottlenecks when adding a large number of products at once. Each individual addition incurred some overhead, such as individual processing and database operations, resulting in slower response times and potential scalability issues.

To address the above issue, new functionality has been introduced to perform line item bulk processing by using a new URL parameter, Boolean useBulkProcessing.

API Request Usage

By using the useBulkProcessing parameter in the URL, developers can enhance their interaction with our REST API endpoint. By including this parameter in requests, developers can efficiently manage large shopping baskets without the need for complex code changes.

To demonstrate the usage, the following URL serves as example:

URL Sample
https:/{baseUrl}/baskets/{basketID}/items

In the above URL example, append the new parameter useBulkProcessing to the URL with the value true to enable the bulk processing functionality:

URL with new parameter
https:/{baseUrl}/baskets/{basketID}/items?useBulkProcessing=true

By incorporating the parameter into the requests, developers can take full advantage of the new large basket approach and optimize the management of large collections of line items within their online shops.

For more information on the execution of single and multiple processing handlers, see Concept - Basket Handling | Concept BasketHandling Add to BasketOperation (bulkoperations).


Basket Payment Resource

Get Eligible Payment Methods

This provides all payment methods (also known as payment services) that are eligible for the current user and basket. An include section containing all related payment instruments is provided on demand (URL query parameter include=paymentInstruments). This section contains all payment instruments created for all eligible payment methods, i.e. the ones created for the user as well as for the basket. Payment instruments of payment methods that are not eligible are not returned.

In case a payment method is not usable at the moment, but would have minor changes in the basket, it is listed with the flag "restricted". In case the service connector provides a reason, it is available in the list of "restrictions".

For payment methods without parameters that currently have no related payment instrument instance, a payment instrument with a synthetic ID is provided by default. The paymentInstruments attribute contains one entry with the same value as the id attribute in this case. The specific payment instrument instance will be created on the fly by the server if this payment instrument is assigned to the basket.

The first example shows a list of eligible payment methods: one without restrictions, the other one with the limitation that the defined maximum order amount for this method was exceeded.

Response: GET /baskets/<basketID>/eligible-payment-methods?include=paymentInstruments
{
    "data": [
        {
            "default": false,
            "description": "Just pay your order directly when it gets delivered!",
            "displayName": "Cash on Delivery",
            "id": "ISH_CASH_ON_DELIVERY",
            "paymentInstruments": [
                "ISH_CASH_ON_DELIVERY"
            ],
            "restricted": false,
            "saveAllowed": false
        },
        {
            "default": false,
            "description": "Paying by invoice is easy and comfortable - give it a try!",
            "displayName": "Invoice",
            "id": "ISH_INVOICE",
            "maxOrderAmount": {
                "gross": {
                    "currency": "USD",
                    "value": 1000
                }
            },
            "minOrderAmount": {
                "gross": {
                    "currency": "USD",
                    "value": 500
                }
            },
            "paymentCostsThreshold": {
                "net": {
                    "currency": "USD",
                    "value": 0
                }
            },
            "paymentInstruments": [
                "ISH_INVOICE"
            ],
            "restricted": true,
            "restrictions": [
                {
                    "code": "payment.restriction.MaxOrderAmount",
                    "message": "The maximum order amount for this payment method has been exceeded."
                }
            ],
            "saveAllowed": false
        }
    ],
    "included": {
        "paymentInstruments": {
            "ISH_CASH_IN_ADVANCE": {
                "id": "ISH_CASH_IN_ADVANCE"
            },
            "ISH_INVOICE": {
                "id": "ISH_INVOICE"
            }
        }
    }
}

Provide Metadata for Payment Parameters

The details of the payment method have to include information (metadata) about the required parameters for the method. On connector side these data are defined by PropertyGroups. 

The metadata have to include information about

  • Needed fields (names, labels and type)
  • Required or optional
  • Type of display (hidden, text input, ...)
  • Syntactical validation via simple constraints

The following code snippet gives an example of how the  representation of the payment parameters to be provided by the user interface my look like. Normally that means that the user has to enter them. The only exception are parameters annotated with "hidden". These are calculated in the UI or by the provider integration scripts. A prominent example for such a scenario are payment pages hosted by the payment service provider.

Response: GET /baskets/<basketID>/eligible-payment-methods?include=paymentInstruments
{
    "data": [{
        "restricted": false,
        "default": false,
        "description": "...",
        "displayName": "Direct Debit Transfer",
        "id": "ISH_DEBIT_TRANSFER",
        "saveAllowed": true,
        "parameters": [{
                "name": "iban",
                "displayName": "IBAN",
                "description": "Enter your International Bank Account Number.",
                "type": "string",
                "placeholder": "DE12-3456-7890"
                "hidden": false,
                "constraints": [
                    {
                         "required": { 
                                "message": "The IBAN is required."
                          },
                    },
                    {
                          "size": {
                                "min": 15,
                                "max": 34,
                                "message": "The IBAN must have a length of 15 to 34 characters."
                          },
                    },
                    {
                          "pattern": {
                                "regexp": "^[A-Z]{2}[0-9]{2}([\-\ ]{0,1}[0-9A-Z]{4}){4}[\-\ 0-9A-Z]{0,4}",
                                "message": "The IBAN structure is invalid."
                          }
                    }
                ]
             }
        ]
    }]
}

Mapping of Annotations

Java Bean Validation AnnotationConstraint NameComment

NotNull

required
Sizesize
PatternpatternJava regex pattern without any change is handed out
Futurefuture
Pastpast

Extend Annotation Mapping

The REST API supports five basic - but most important - JavaBean annotations. In case more annotations are required, the functionality can easily be extended. To do so, a customer ConstraintRO needs to be provided together with a Function implementation to map the data from the annotation to the resource object.

JavaBean Annotation Mapper Extensions
// Provides a resource object for a custom Annotation "@MyMin" defining the lower limit of an integer
public class MyMinConstraintRO extends ConstraintRO
{
    public static final String TYPE_NAME = "my-min";
    private final int minValue;
    
    public MyMinConstraintRO(String message, int minValue)
    {
        super(TYPE_NAME, message);
        this.minValue = minValue;
    }

    public int getMinValue()
    {
        return minValue;
    }
}

// Do the mapping in a special function
public class MyMinConstraintROMapper implements Function<MyMin, MyMinConstraintRO>
{
    @Inject @Constraint
    private Function<String, String> messageMapper;

    @Override
    public MyMinConstraintRO apply(MyMin mymin)
    {
        String message = messageMapper.apply(mymin.message());
        return new MyMinConstraintRO(message, mymin.minimum());
    }
}

// the new mapping needs to be registed
public class AppSfRestCommonMapperModule extends AbstractModule
{
    @Override
    protected void configure()
    {
            MapBinder<Class<?>, Function<? extends Annotation, ? extends ConstraintRO>> constraintMappers = MapBinder
                    .newMapBinder(binder(), new TypeLiteral<Class<?>>() {}, new TypeLiteral<Function<? extends Annotation, ? extends ConstraintRO>>() {});
            constraintMappers.addBinding(MyMin.class).to(MyMinConstraintROMapper.class);
    }
}

Get Active Payments

Using the request, the client can resolve the list of active (limited and open tender) payments assigned to the current basket. The request supports includes to retrieve also the related payment methods and payment instruments in a single request.

Response: GET /baskets/<basketID>/payments?include=paymentInstrument,paymentMethod
{
    "data": [
        {
            "baseAmount": {
                "gross": {
                    "currency": "USD",
                    "value": 13055.07
                }
            },
            "id": "open-tender",
            "paymentCosts": {
                "gross": {
                    "currency": "USD",
                    "value": 0
                },
                "net": {
                    "currency": "USD",
                    "value": 0
                },
                "tax": {
                    "currency": "USD",
                    "value": 0
                }
            },
            "paymentInstrument": "ISH_CASH_ON_DELIVERY",
            "paymentMethod": "ISH_CASH_ON_DELIVERY",
            "totalAmount": {
                "gross": {
                    "currency": "USD",
                    "value": 13055.07
                }
            }
        }
    ],
    "included": {
        "paymentMethod": {
            "ISH_CASH_ON_DELIVERY": {
                "default": false,
                "description": "Just pay your order directly when it gets delivered!",
                "displayName": "Cash on Delivery",
                "id": "ISH_CASH_ON_DELIVERY",
                "paymentInstruments": [
                    "ISH_CASH_ON_DELIVERY"
                ],
                "restricted": false,
                "saveAllowed": true
            }
        },
        "paymentInstrument": {
            "ISH_CASH_ON_DELIVERY": {
                "id": "ISH_CASH_ON_DELIVERY"
            }
        }
    }
}

Create a Payment Instrument

The request is intended to allow saving the customer entered data at the basket. It is not required in case the payment method does not have data to be saved (technically: no PropertyGroup returned by getPaymentParameterDescriptors(PaymentContext)).

Request: POST /baskets/<basketID>/payment-instruments?include=paymentMethod
{
    "paymentMethod" : "ISH_DIRECT_DEBIT",
    "parameters" : [
        {
            "name": "IBAN",
            "value": "DE12345678901234"
        },
		{
            "name": "holder",
            "value": "Patricia Miller"
        }
    ]
}
Response: POST /baskets/<basketID>/payment-instruments?include=paymentMethod
{
    "data": {
        "accountIdentifier": "************1234",
        "id": "3EQKAB2_MmMAAAFqY89pwU8_",
        "parameters": [
            {
                "name": "holder",
                "value": "Patricia Miller"
            },
            {
                "name": "IBAN",
                "value": "************1234"
            }
        ]
    }
}

Assign a Payment to the Basket

This assigns a new payment to the basket. In case the new payment is an open tender payment and there is already such a payment assigned to the basket, the request will fail. The old open tender payment needs to be removed first. In case the payment is a limited tender payment, an existing open tender may be removed automatically if the limited tender completely covers the basket. If there is a limited tender which completely covers the basket, then an open tender payment cannot be created without removing the limited tender payment first.

Request: POST /baskets/<basketID>/payments/
{
    "paymentInstrument" : "4j0KAB2_28MAAAFuueJdhmPp"
}
Response: POST /baskets/<basketID>/payments/
{
    "data": {
        "baseAmount": {
            "currency": "USD",
            "value": 628.34
        },
        "id": "6vYKAB2_Qa0AAAFuTnNdhmPq",
        "openTender": true,
        "paymentCosts": {
            "gross": {
                "currency": "USD",
                "value": 0.00
            },
            "net": {
                "currency": "USD",
                "value": 0.0
            },
            "tax": {
                "currency": "USD",
                "value": 0.00
            }
        },
        "paymentInstrument": "d3EKAB2_dhUAAAFu_iJdhmPn",
        "paymentMethod": "ISH_DEBIT_TRANSFER",
        "redirectRequired": false,
        "status": "Unprocessed",
        "totalAmount": {
            "currency": "USD",
            "value": 628.34
        }
    }
}

Create/Replace Open Tender Payment

Only a single open tender payment can be assigned to the basket. In order to reduce the effort for the client for deleting the old open tender payment and assigning a new one, a shortcut is possible. The API provides an alias for the active open tender payment at the basket, which can be used to create or replace it with a single request. Similar to the POST /baskets/<basketID>/payments/ request, an open tender payment can only be created if there is no limited tender payment that fully covers the basket. In that case the limited tender payment would have to be removed first.

Request: PUT /baskets/<basketID>/payments/open-tender?include=paymentInstrument,paymentMethod
{
    "paymentInstrument" : "3EQKAB2_MmMAAAFqY89pwU8_"
}
Response: PUT /baskets/<basketID>/payments/open-tender?include=paymentInstrument
{
    "data": {
        "baseAmount": {
            "gross": {
                "currency": "USD",
                "value": 628.34
            }
        },
        "id": "open-tender",
        "paymentCosts": {
            "gross": {
                "currency": "USD",
                "value": 0
            },
            "net": {
                "currency": "USD",
                "value": 0
            },
            "tax": {
                "currency": "USD",
                "value": 0
            }
        },
        "paymentInstrument": "3EQKAB2_MmMAAAFqY89pwU8_",
        "paymentMethod": "ISH_DEBIT_TRANSFER",
        "redirectRequired": false,
        "totalAmount": {
            "gross": {
                "currency": "USD",
                "value": 628.34
            }
        }
    },
    "included": {
        "paymentInstrument": {
            "3EQKAB2_MmMAAAFqY89pwU8_": {
                "accountIdentifier": "************1234",
                "id": "3EQKAB2_MmMAAAFqY89pwU8_",
                "parameters": [
                    {
                        "name": "holder",
                        "value": "Patricia Miller"
                    },
                    {
                        "name": "IBAN",
                        "value": "************1234"
                    }
                ]
            }
        }
    }
}

Remove a Payment

This removes the payment from the basket. See the following example for details:

Response: DELETE /baskets/<basketID>/payments/<paymentID>
{
    "infos": [
        {
            "code": "payment.deletion.info",
            "message": "The payment has been deleted.",
            "status": "200"
        }
    ]
}

Remove a Payment Instrument

This removes the payment instrument from the basket. In case it was currently assigned as active payment, the payment is deleted, too.

Response: DELETE /baskets/<basketID>/payment-instruments/<paymentInstrumentID>
{
    "infos": [
        {
            "code": "payment-instrument.deletion.info",
            "message": "The payment instrument has been deleted.",
            "status": "200"
        }
    ]
}

Prepare and Handle Redirect

General Workflow


Prepare Redirect While Creating Payment

These requests are only supported if the payment method supports a kind of redirecting workflow. The request could be used for all kinds of redirect.

One possibility to provide the three required URLs is the Create Payment request.

Request: PUT /baskets/<basketID>/payments/open-tender
{
    "instrument": "ThePaymentInstrumentUUID",
    "redirect": {
        "successUrl": "http://storefront.url/success",
        "cancelUrl": "http://storefront.url/cancel",
        "failureUrl": "http://storefront.url/failure"
    }
}
Response: PUT /baskets/<basketID>/payments/open-tender
{
    "data": {
        "baseAmount": {
            "gross": {
                "currency": "USD",
                "value": 13055.07
            }
        },
        "id": "open-tender",
        "paymentCosts": {
            "gross": {
                "currency": "USD",
                "value": 0
            },
            "net": {
                "currency": "USD",
                "value": 0
            },
            "tax": {
                "currency": "USD",
                "value": 0
            }
        },
        "paymentInstrument": "ISH_CASH_ON_DELIVERY",
        "paymentMethod": "ISH_CASH_ON_DELIVERY",
        "totalAmount": {
            "gross": {
                "currency": "USD",
                "value": 13055.07
            }
        },
        "redirect": { 
           "redirectUrl": "https://server.payment-provider.com/"
        }
    }
}

The same approach can be used if POST /baskets/<id>/payments  is supported.

Prepare Redirect Using Separate Request

Alternatively, a separate request to a dedicated resource is possible. The structure is basically the same. The difference is that only the content of the "redirect" section is used in the request. By providing this alternative request, the client can choose the best option for its implementation. In most cases the ID will be open-tender (LimitedTender payments would have to use the ID, but these kinds of payment methods usually do not use redirect.)

Request: PATCH /baskets/<basketID>/payments/<paymentID>
{
    "redirect": {
        "successUrl": "http://storefront.url/successPage?paymentID=0815", 
        "cancelUrl": "http://storefront.url/cancel", 
        "failureUrl": "http://storefront.url/failure"
    }
}

The response is the same as in the section above (POST /.../payments).

Handle Callback From Redirect

In case of "redirect before checkout" there is only one single option: The redirect must be completed before the order can be created. That means that there is no need for a special handling for closed browser windows. In such a case the basket is still available and no special handling is required. This is completely different in case of a redirect after checkout and will be described at the order resource.

Request: PATCH /baskets/<basketID>/payments/<paymentID>
{
    "redirect": 
    {
        "parameters" : [ 
           { 
               "name": "transactionID", 
               "value": "id from provider" 
           }
        ],
        "status": "success" // map to the redirect status (valid values: success, cancel, failure) mapped by the client from the called URL to these values
    }
}
Response: PATCH /baskets/<basketID>/payments/<paymentID>
{
    "data": {
        "baseAmount": {
            "gross": {
                "currency": "USD",
                "value": 1046.4
            }
        },
        "id": "open-tender",
        "paymentCosts": {
            "gross": {
                "currency": "USD",
                "value": 0
            },
            "net": {
                "currency": "USD",
                "value": 0
            },
            "tax": {
                "currency": "USD",
                "value": 0
            }
        },
        "paymentInstrument": "ifUKAB2_yPIAAAFqGhxaH7rb",
        "paymentMethod": "ISH_CREDITCARD",
        "redirect": {
            "cancelUrl": "http://storefront.url/cancel",
            "failureUrl": "http://storefront.url/failure",
            "parameters": [
                {
                    "name": "Status",
                    "value": "Success"
                },
                {
                    "name": "transactionID",
                    "value": "id from provider"
                },
                {
                    "name": "RedirectAmount",
                    "value": {
                        "currencyMnemonic": "USD",
                        "value": 1046.4,
                        "available": true
                    }
                }
            ],
            "redirectUrl": "http://icm-server/INTERSHOP/web/WFS/inSPIRED-inTRONICS-Site/en_US/-/USD/ISHPayRedirect-3DSecure;pgid=VWGQ3pi7ldqRpDkHwv2g8e9l0000UMdp5y8P;sid=0BQKAB2_FXEAAAFq3t8CvdWC?merchant=0815&password=intershop&service=in4KAB2_qLcAAAFp9fd4YuOd&amount=%24+1%2C046.40¤cy=USD&card_number=4111111111111111&card_type=vsa&successURL=http%3A%2F%2Fstorefront.url%2Fsuccess&failURL=http%3A%2F%2Fstorefront.url%2Ffailure&cancelURL=http%3A%2F%2Fstorefront.url%2Fcancel",
            "status": "SUCCESS",
            "successUrl": "http://storefront.url/success"
        },
        "redirectRequired": false,
        "totalAmount": {
            "gross": {
                "currency": "USD",
                "value": 1046.4
            }
        }
    }
}

Basket Quote Resource

The REST sub-resource 'quotes' is available from ICM version 7.10.38.

.../baskets/<basket-id>/quotes

The endpoint allows to add/remove a quote instead of single items.

Add Quote

A quote can be added to the basket with the following request:

POST .../baskets/<basket-id>/quotes

// Request payload
{
    {
        "calculated" : true|false,
        "id" : "123",
    }
}

// Response payload - success
{
    "data" : {
        "calculated" : true|false,
        "id" : "123",
        "displayName" : "For me only",
        "description" : "Best prices ever",
        "number" : "0123456789",
        "creationDate" : "1635428413969",
        "validFromDate" : "1635428400000",
        "validToDate" : "1636036800000",
        "sellerComment" : "I will go bankrupt!",
        "total" : {
          "net":{
            "currency": "USD",
            "value": 514.68
          } 
        }
    },
    "links" : [{
        // link to .../baskets/<basket-id>/quotes/<quote-id>
    }
    ... ]
    "infos" : [{
    },
    ... ]
}

// Response payload - failure
{
    "errors" : [{
    },
    ... ]
}

Retrieve all Quotes of the Basket

The quotes contained in the basket can be retrieved by the following request:

GET .../baskets/<basket-id>/quotes

// Response payload
{
    [{
        "calculated" : true|false,
        "id" : "123",
        "displayName" : "For me only",
        "description" : "Best prices ever",
        "number" : "0123456789",
        "creationDate" : "1635428413969",
        "validFromDate" : "1635428400000",
        "validToDate" : "1636036800000",
        "sellerComment" : "I will go bankrupt!",
        "total" : {
            "net":{
              "currency": "USD",
              "value": 514.68
          } 
        }
    },
    {
        "calculated" : true|false,
        "id" : "456",
        "displayName" : "For me only again",
        "description" : "Very best prices ever",
        "number" : "9876543210",
        "creationDate" : "1635428413969",
        "validFromDate" : "1635428400000",
        "validToDate" : "1636036800000",
        "sellerComment" : "I am bankrupt now!",
        "total" : {
            "net":{
              "currency": "USD",
              "value": 25678.68
          } 
        }
    }]
}

Remove Quote

One or more quotes can be removed from the basket with the following request:

DELETE .../baskets/<basket-id>/quotes/<quote-id>

// Response payload
{
    "infos": [
        {
            "code": "basket.delete_quote.info",
            "message": "The quote was deleted from the basket.",
            "status": "200"
        }
    ]
}

There are no other requests for the basket-quote item resource currently.


Disclaimer
The information provided in the Knowledge Base may not be applicable to all systems and situations. Intershop Communications will not be liable to any party for any direct or indirect damages resulting from the use of the Customer Support section of the Intershop Corporate Web site, including, without limitation, any lost profits, business interruption, loss of programs or other data on your information handling system.
The Intershop Knowledge Portal uses only technically necessary cookies. We do not track visitors or have visitors tracked by 3rd parties. Please find further information on privacy in the Intershop Privacy Policy and Legal Notice.
Home
Knowledge Base
Product Releases
Log on to continue
This Knowledge Base document is reserved for registered customers.
Log on with your Intershop Entra ID to continue.
Write an email to supportadmin@intershop.de if you experience login issues,
or if you want to register as customer.