Documentation
Feedback
Guides

Tax service asynchronous integration

If you use synchronous tax service integration, you might find some limitations:

  • Timeout for the request is five seconds.
  • There is no retry in case of timeout.
  • If the external service that responds to the request times out constantly, the store will not be able to finish the order.
  • If this integration is active, it applies to all stores in that account.

For stores in which there are often up to hundreds of items in a cart, like some B2B operations, this flow can become inefficient and expensive. In this case, consider using asynchronous integration.

Asynchronous integration

Asynchronous integration is an alternative that offers a better user experience, as it ensures that the flow will always have the taxes at the right time, although it depends directly on the resilience of third parties.

By definition, this type of integration allows other processes to move forward while it waits for a response from the tax engine. Thus, the system will not respond with a timeout even if it takes more than 5 seconds to respond.

Instead of calling the external tax service API for each item added to the cart, asynchronous integration will send just one request resulting in less data being processed, and thus checkout becomes faster and more efficient. That request can be triggered, for instance, by an event in the checkout UI.

Implementing asynchronous integration

To use asynchronous integration, Checkout can not be configured to handle the External Tax Services. This configuration should only be done for synchronous integration. To use asynchronous integration, make sure that the response from the Checkout Configuration API has the taxConfiguration object with the value null. If not, use the Checkout Configuration UPDATE request to make it null.

The asynchronous call to the tax engine does not require any configuration. It must be implemented by the store, as described in this recipe. It is usually triggered by an event or button in the checkout UI.

To query the tax engine, the implementation must follow this flow:

  • Get the orderForm.
  • Calculate taxes (or get calculation from the external provider).
  • Submit response with taxes.

Getting the orderForm

To obtain the orderForm, the implementation must use the following request:

  • Method: GET
  • URL: https://{accountName}.{environment}.com.br/api/checkout/pub/orderForm/{orderFormId}?disableAutoCompletion=true

The disableAutoCompletion=true parameter is necessary to ensure that the requested orderForm won’t be recalculated but delivered exactly as it was at the time of the request.

Although the route is public (/pub), it is necessary to use credentials (appKey and appToken) with permission to access the cart data to obtain the unmasked data.

Calculating taxes and sending the response

Having obtained the orderForm, the implementation must calculate the appropriate taxes, or get the appropriate calculations from the external provider, and send the following information in the response:

  • itemTaxResponse: an array of items (SKUs), each containing an array of applicable taxes.
  • miniCartRequest: an object containing the items, delivery address, buyer data, orderForm ID, and trade policy of the cart receiving the taxes.

Taxes should be sent to the following endpoint:

  • Method: POST
  • URL: https://{accountName}.vtexcommercestable.com.br/api/checkout/pvt/orderForms/taxes

Below is an example body.

This request requires the appKey and appToken credentials.


_73
{
_73
"itemTaxResponse": [
_73
{
_73
"sku": "8",
_73
"taxes": [
_73
{
_73
"name": "Tax1",
_73
"value": 1.28
_73
},
_73
{
_73
"name": "Tax2",
_73
"value": 7.91
_73
}
_73
]
_73
},
_73
{
_73
"sku": "33", // SKU id
_73
"taxes": [
_73
{
_73
"name": "Tax1", // name you want to use for the tax
_73
"value": 3.98
_73
}
_73
]
_73
}
_73
],
_73
"miniCartRequest": {
_73
"orderFormId": "9c7aad42ee2d4a37a23478a9d5cb6f30",
_73
"salesChannel": "1",
_73
"items": [
_73
{
_73
"sku": 8,
_73
"ean": null,
_73
"refId": "1111A",
_73
"unitMultiplier": 1,
_73
"measurementUnit": "un",
_73
"targetPrice": 80, // price
_73
"itemPrice": 240, // total price (price * qty * unitMultiplier)
_73
"discountPrice": 0, // item discounts
_73
"freightPrice": 0.9, // item’s freight price
_73
"quantity": 3,
_73
"dockId": "1",
_73
"brandId": 2000000
_73
},
_73
{
_73
"sku": 33,
_73
"ean": null,
_73
"refId": "1111B",
_73
"unitMultiplier": 1,
_73
"measurementUnit": "un",
_73
"targetPrice": 20,
_73
"itemPrice": 40,
_73
"discountPrice": 0,
_73
"freightPrice": 0.6,
_73
"quantity": 2,
_73
"dockId": "1",
_73
"brandId": 2000000
_73
}
_73
],
_73
"shippingDestination": { // required!
_73
"country": "BRA",
_73
"state": "RJ",
_73
"city": "Rio de Janeiro",
_73
"neighborhood": "Botafogo",
_73
"postalCode": "22250-040",
_73
"street": "Praia de Botafogo"
_73
},
_73
"clientData": {
_73
"email": "email@gmail.com.br",
_73
"document": "01234567890",
_73
"corporateDocument": null
_73
}
_73
}
_73
}

Validating taxes

Note that the tax engine response includes, in addition to the taxes, the minicart that was used for the calculation. So, VTEX is able to guarantee that the calculated tax is consistent with the cart that is completing the purchase. This happens through the following algorithm:

  • When the system receives the response from the tax provider, it gets the minicart that was used to calculate the taxes.
  • The system generates a token for this minicart and saves it in the cart.
  • When the purchase is concluded, the token is sent to the seller, who checks whether it matches the cart that is completing the purchase.
  • If it is the same token, the purchase is completed, with the tax applied. If the tokens do not match, the purchase is denied.
  • If the purchase is denied, there will be a 500 error in the request /transaction: “The order cannot be created. Please try again."

The implementer is responsible for the minicart. Note that it is crucial for validating taxes, so there must be an exact match with the customer's current cart.

If the system takes too long to apply the tax, you can create an order without taxes.

If the system takes too long to review the tax after changes to the cart, it will not be possible to complete the order.

Example of order object

Finally, see an example of an order object at VTEX after taxes are applied. Note that they have been included in the totals array.


_226
{
_226
"emailTracked": "0df1ee8d7f58474782c3750e2f42e4ed@ct.vtex.com.br",
_226
"approvedBy": null,
_226
"cancelledBy": null,
_226
"cancelReason": null,
_226
"handlingData": null,
_226
"orderId": "v3613574JRSA-01",
_226
"sequence": "3613574",
_226
"marketplaceOrderId": "",
_226
"marketplaceServicesEndpoint": "http://oms.vtexinternal.com.br/api/oms?an=mystore",
_226
"sellerOrderId": "00-v3613574JRSA-01",
_226
"origin": "Marketplace",
_226
"affiliateId": "",
_226
"salesChannel": "1",
_226
"merchantName": null,
_226
"status": "ready-for-handling",
_226
"statusDescription": "Pronto para o manuseio",
_226
"value": 598095,
_226
"creationDate": "2020-05-26T17:37:56.2353707+00:00",
_226
"lastChange": "2020-05-26T17:39:24.4238867+00:00",
_226
"orderGroup": null,
_226
"totals": [
_226
{
_226
"id": "Items",
_226
"name": "Total de los items",
_226
"value": 656890
_226
},
_226
{
_226
"id": "Discounts",
_226
"name": "Total de descuentos",
_226
"value": 0
_226
},
_226
{
_226
"id": "Shipping",
_226
"name": "Costo total del envío",
_226
"value": 0
_226
},
_226
{
_226
"id": "Tax",
_226
"name": "Costo total del cambio",
_226
"value": 0
_226
},
_226
{
_226
"id": "CustomTax",
_226
"name": "FI_ SOCIOS PREMIUM ",
_226
"value": 297
_226
},
_226
{
_226
"id": "CustomTax",
_226
"name": "VI_P 3X2_BEBIDAS ",
_226
"value": 400
_226
}
_226
],
_226
"items": [
_226
{
_226
"uniqueId": "892FF75C59301ACE8CBE75BA7P0E1BE9",
_226
"id": "4321",
_226
"productId": "1234",
_226
"ean": "9974111597732",
_226
"lockId": "00-v3612391AKPI-01",
_226
"itemAttachment": {
_226
"content": {},
_226
"name": null
_226
},
_226
"attachments": [],
_226
"quantity": 1,
_226
"seller": "1",
_226
"name": "My Product",
_226
"refId": "11570114019",
_226
"price": 5750,
_226
"listPrice": null,
_226
"manualPrice": null,
_226
"priceTags": [],
_226
"imageUrl": "https://mystore.vteximg.com.br/arquivos/ids/521666-55-55/myproduct-12-U-1-2256.jpg?v=536862711303520990",
_226
"detailUrl": "/my-product/p",
_226
"components": [],
_226
"bundleItems": [],
_226
"params": [],
_226
"offerings": [],
_226
"sellerSku": "2511",
_226
"priceValidUntil": null,
_226
"commission": 0,
_226
"tax": 0,
_226
"preSaleDate": null,
_226
"additionalInfo": {
_226
"brandName": "BRAND",
_226
"brandId": "1190",
_226
"categoriesIds": "/1/29/201/",
_226
"categories": [
_226
{
_226
"id": 201,
_226
"name": "Category1"
_226
},
_226
{
_226
"id": 29,
_226
"name": "Category2"
_226
},
_226
{
_226
"id": 1,
_226
"name": "Category3"
_226
}
_226
],
_226
"productClusterId": "1171,1401,2643,2832,4121,4318,4342",
_226
"commercialConditionId": "1",
_226
"dimension": {
_226
"cubicweight": 0.0002,
_226
"height": 1,
_226
"length": 1,
_226
"weight": 1,
_226
"width": 1
_226
},
_226
"offeringInfo": null,
_226
"offeringType": null,
_226
"offeringTypeId": null
_226
},
_226
"measurementUnit": "un",
_226
"unitMultiplier": 1,
_226
"sellingPrice": 5750,
_226
"isGift": false,
_226
"shippingPrice": null,
_226
"rewardValue": 0,
_226
"freightCommission": 0,
_226
"priceDefinitions": null,
_226
"taxCode": null,
_226
"parentItemIndex": null,
_226
"parentAssemblyBinding": null,
_226
"callCenterOperator": null,
_226
"serialNumbers": null,
_226
"assemblies": [],
_226
"costPrice": null
_226
}
_226
],
_226
"marketplaceItems": [],
_226
"clientProfileData": {
_226
"id": "clientProfileData",
_226
"email": "email@gmail.com",
_226
"firstName": "John",
_226
"lastName": "Doe",
_226
"documentType": "DNI",
_226
"document": "12345678",
_226
"phone": "+55012345678",
_226
"corporateName": null,
_226
"tradeName": null,
_226
"corporateDocument": null,
_226
"stateInscription": null,
_226
"corporatePhone": null,
_226
"isCorporate": false,
_226
"userProfileId": "1c87654df-f25c-49jf-9e9f-4839c00009a6",
_226
"customerClass": null
_226
},
_226
"giftRegistryData": null,
_226
"marketingData": null,
_226
"ratesAndBenefitsData": {
_226
"id": "ratesAndBenefitsData",
_226
"rateAndBenefitsIdentifiers": [
_226
{
_226
"description": "christmas2020",
_226
"featured": true,
_226
"id": "011p7fbc-2129-424e-b45e-4b53fa8d4805",
_226
"name": "christmas2020",
_226
"matchedParameters": {
_226
"productCluster@CatalogSystem": "4848|inclusive"
_226
},
_226
"additionalInfo": null
_226
}
_226
]
_226
},
_226
"shippingData": {
_226
...
_226
},
_226
"paymentData": {
_226
...
_226
},
_226
"packageAttachment": {
_226
"packages": []
_226
},
_226
"sellers": [
_226
{
_226
"id": "1",
_226
"name": "My Store",
_226
"logo": "",
_226
"fulfillmentEndpoint": "http://fulfillment.vtexcommerce.com.br/api/fulfillment?sc=1&an=mystore"
_226
}
_226
],
_226
"callCenterOperatorData": null,
_226
"followUpEmail": "email@vtex.com",
_226
"lastMessage": null,
_226
"hostname": "storehostname",
_226
"invoiceData": null,
_226
"changesAttachment": null,
_226
"openTextField": null,
_226
"roundingError": 0,
_226
"orderFormId": "48x123e0baff36718d0nc81e56cec29c",
_226
"commercialConditionData": null,
_226
"isCompleted": true,
_226
"customData": null,
_226
"storePreferencesData": {
_226
"countryCode": "ARG",
_226
"currencyCode": "ARS",
_226
"currencyFormatInfo": {
_226
"CurrencyDecimalDigits": 2,
_226
"CurrencyDecimalSeparator": ",",
_226
"CurrencyGroupSeparator": ".",
_226
"CurrencyGroupSize": 3,
_226
"StartsWithCurrencySymbol": true
_226
},
_226
"currencyLocale": 11274,
_226
"currencySymbol": "$",
_226
"timeZone": "Argentina Standard Time"
_226
},
_226
"allowCancellation": false,
_226
"allowEdition": false,
_226
"isCheckedIn": false,
_226
"marketplace": {
_226
"baseURL": "http://oms.vtexinternal.com.br/api/oms?an=mystore",
_226
"isCertified": null,
_226
"name": "mystore"
_226
},
_226
"authorizedDate": "2020-05-26T17:38:10.2154236+00:00",
_226
"invoicedDate": null,
_226
"itemMetadata": null,
_226
"subscriptionData": null,
_226
"taxData": null,
_226
"checkedInPickupPointId": null,
_226
"cancellationData": null
_226
}

Contributors
3
Photo of the contributor
Photo of the contributor
Photo of the contributor
Was this helpful?
Yes
No
Suggest Edits (GitHub)
Contributors
3
Photo of the contributor
Photo of the contributor
Photo of the contributor
On this page