Point of Sale (POS) Integration Guide

Introduction

Sales/Refunds

Sales

Special fields in a sales order

Create/update  a sales order

Query options

Refunds

Create/update refund

Query options

Inventory

Query options

Customer

Create/update customer

Query options

  1. Introduction

The purpose of this guide is to describe how to use the Vintrace REST API to provide Vintrace with sales and refund data from your Point of Sales (POS) or eCommerce system. A REST API that allows your POS/eCommerce system to query available stock levels is also available.

Detailed REST API documentation can be found in the vintrace apiary.

  1. Authentication

The vintrace API uses Basic HTTP authentication for REST requests. Basic HTTP authentication uses a Base64 encoded username and password separated by a colon (:) character and is added to an authorization header. For example, if your username is myusername and your password is mypassword, you would send the following header:

                     Authorization: Basic bXl1c2VybmFtZTpteXBhc3N3b3Jk

Where the text after Basic is the Base64 representation of myusername:mypassword

  1. Date formats

The date is specified as the number of milliseconds that have elapsed since epoch January 1, 1970.

Example:  UTC Sun Aug 27 2017 14:00:00 is represented as 1503842400000  

  1. External references

There are fields in our API where you can supply either the Vintrace internal ID (eg customerId) for a record or the human readable name (eg customerName).  For these fields, we recommend using the Vintrace internal ID if your software supports it, as this is less likely to change than the corresponding customer name.  More details on these fields can be found in the relevant sections.

  1. Sales and Refunds

Vintrace uses sales and refund information to track industry specific taxes such as WET and NZ Excise, as well as deplete stock levels from dedicated storage areas based on POS and eCommerce sales transactions.

  1. Sales

A sales orders lists the items that have been sold to a customer.

Each sales order is associated with a price list. The price list determines the prices used for items.  The price list in the sales order gives the flexibility to charge different amounts for your goods based on individual customer, vintage, or type of sale (fore example, retail or wholesale).

Each sales order line item represents each individual sales item and you can configure the revenue account and tax rate per item. The revenue account tracks the revenue generated out of the sales, and can be configured from the price list or can be provided for the individual items in the sales order. Tax rates can be configured from price lists or can be provided for the individual items in the sales order.

We recommend that you group your  sales transactions per customer per outlet per day. The sales without any customer data on it can be grouped under a general customer, for example, WALKIN.

  1. Special fields in a sales order

customerPickup – This field indicates that the sale is a customer pickup, for example, where the sale is from the cellar door where the customer walks out with the goods. If this option is on, Vintrace automatically reduces stock levels for the items in the sales order once it is saved as approved.

storageAreaId/storageAreaCode - When the customerPickup field is set to true, you must enter a storage area name or the Vintrace ID from where the stock levels are reduced for the sale.

disableAccountsSync   Setting this option as true disables the syncing of the sales order with any accounting integrations. For example, if you have Xero accounting integration turned on, you cannot sync this sales order to Xero.

customerId/customerName - The person or customer who bought the stock. You can enter the Vintrace ID of the customer, if known, or the name as saved in Vintrace.

salesPriceListId/salesPriceListName - The pricelist determines prices for the item. You can configure a price list in Vintrace  specifically for the cellar door.

itemId/itemName - The name or ID of the stock item as saved in Vintrace.

accountId/accountName  -  The revenue account tracks the revenue generated on the sale. You can enter the Vintrace ID of the revenue account if known, or the name as saved in Vintrace. This is a non-mandatory field, if no value is entered, it defaults to the revenue account on the sales item/stock item category/sales region/price list of the item. You can enter the Vintrace ID of the price list or a name.  

taxRateId/taxRateName   - Different tax rates can apply to different situations for items. For example, in Australia the Wine Equalisation Tax (WET) tax applies to wine sales but not to the merchandise which can also be on the same price list. You can configure a tax rate for wine sales that has a WET tax component and a different tax rate for your merchandise sales where WET tax is not applied. This is a non-mandatory field, if no value is entered, it defaults to the tax rate of the price list used. You can enter the Vintrace ID of the tax rate or the name as saved in Vintrace.

discountPct/adjustment - For sales order with discounts and accounting integration with Xero is turned on for the customer, enter the discount per item as percentage value in discountPct field. Otherwise, if accounting integration is off, enter the discount as a dollar value using the adjustment field.

  1. Create/update  a sales order

To update a sales order, you must provide the ID of the sales order to be updated, otherwise a new sales order is created.

When you want to deplete stock for the sale, you need to set the customerPickup field to true and set a location in the storageAreaCode field from where the stock is to be depleted. If the API user has a favourite pickup storage area set, this is automatically set in the storageAreaCode field if you don’t enter a value. To set a pickup storage area as favourite in Vintrace

  1. Select Accounts > Sales orders.
  2. Open a sales order and select the Customer pickup field.
  3. Select the storage area, then click the heart icon.


If you do not want to send the sales order to a third party accounting integration , for example Xero, set the
disableAccountsSync to true.

POST

http://<base_api_url>/api/v6/sales-order

Field

(items in red are mandatory on create)

Type

Description

id

Integer

To be provided if the request is to update an existing sales order, otherwise a new sales order is created each time.

code

String

Unique name for sales order, if not provided, it is auto generated.

customerId

Integer

Either provide  Vintrace ID or Vintrace customer name.

customerName

String

orderDate

Date

Order date

invoiceDate

Date

Invoice date

salesType

String

Possible values: Retail, Wholesale, Staff

salesPriceListName

 String

Price list to be used for the sales order. You can provide either the name or the ID.

salesPriceListId

Integer

salesOrderStatus

String

Possible values: New, Approved, Payment in progress, Paid.

description

String

 

reference

String

 

wineryId

Integer

This should be provided by name or ID for multiple winery Vintrace servers.

wineryName

String

fulfillment

String

Auto resolved as Fully sent

fulfillmentDate

Date

The date that the stock is reduced or dispatched

salesRegionId

Integer

Either provide ID or name of the sales region.

salesRegionCode

String

notes

String

 

customerPickup

Boolean

Set as true if stock levels are to be reduced.

disableAccountsSync

Boolean

Set as true if you do not want to sync the sales order to an accounting integration, eg, Xero

ignoreStockError

Boolean

To ignore error/warning on insufficient stock.

storageAreaId

Integer

Either ID or name can be entered, otherwise resolved as default storage area configured in Vintrace. Mandatory if the customerPickup field is set to true and there is no default storage area configured in vintrace.

storageAreaCode

String

salesOrderItems

Array

Array of items in the sales order

 

itemName

String

Vintrace stock item code or ID.

itemId

Integer

unitPrice

Integer

Unit price of the item

quantity

Integer

Quantity sold

taxRateId

Integer

Auto resolved from price list or can use Vintrace ID if known.

taxRateName

String

Auto resolved from the price list or provide Vintrace code for tax rate.

accountId

Integer

Revenue account

 

accountCode

String

discountPct

Integer

For sales order with discounts and if accounting integration with Xero is turned on for the customer, enter the discount as a percentage value in the discountPct field.

adjustment

Integer

If accounting integration is off, enter the discount in the adjustment field as a dollar value.

Sample create

{

  "customerName": "ABC Wine Company",

  "salesPriceListName": "Retail",

  "salesType": "Retail",

  "salesOrderStatus": "Approved",

  "invoiceDate": 1507860000000,

  "customerPickup": true,

 "storageAreaCode": "Warehouse",

  "disableAccountsSync": true,

  "salesOrderItems": [

        {

          "itemName": "2013 Gloria GSM 750ml",

          "unitPrice": 13.223,

          "quantity": 5,

          "accountCode": "Revenue"

        },

        {

          "itemName": "2014 BSE Cabernet Sauvignon 750ml",

          "unitPrice": 15.5,

          "quantity": 10,

          "discountPct": 10,

          "accountCode": "Revenue"

        }

  ],

  "orderDate": 1507860000000,

  "ignoreStockError": true

}

 

You can view the created sales order using the following endpoints:

 All sales orders  -  http://<base_api_url>/api/v6/sales-orders/list/

 Sales order by ID - http://<base_api_url>/api/v6/sales-orders/<id>

 Sales order by code - http://<base_api_url>/api/v6/sales-orders/?code=<code>

  1. Query options

You can add these parameters to the above end point to filter out the results

For more details see the vintrace apiary.


  1. Refunds

You can process refunds and return of stock using the Vintrace API. You can create a refund for any approved sales order. Creating multiple refunds for a sales order is allowed. Each line item in the sales order corresponds to an equivalent refund line item. When creating the refund, you need to set the sales order name or ID, and specify the item name and the return quantity per refund line item. The unit price in the refund line item is automatically calculated from the corresponding sales order line item. If a discount is specified in the line item of the sales order, the unit price in the refund uses the discounted price.

Below is an example of a sales order and its equivalent full refund where all the items have been returned.

The following must be specified for a refund:

  1. Create/update refund

To update a refund, you must provide the ID of the refund to be updated, otherwise a new refund is created.

POST

http://<domain_url>/api/v6/refund

Field

(items in red are mandatory)

Type

Description

id

Integer

If provided updates the refund.

code

String

Unique name for refund, auto generated if not entered.

refundDate

Date

 Date of the refund

salesOrderName

String

Mandatory in create mode. The sales order you are creating a refund for.

stockReturned

Boolean

Set as true if the stock is returned.

storageAreaId

Integer

Storage area to which stock is returned. Either provide Vintrace ID or the name.

storageAreaName

String

refundStatus

String

Possible values : Approved, Awaiting approval

disableAccountsSync

Boolean

 Set as true if you do not want to sync the refund to an accounting integration, eg, Xero

reference

String

 

notes

String

 

refundLineItems

Array

 

 

itemName

String

Vintrace code for the item

returnQuantity

Integer

 

 

Sample create

 

{

        "refundDate": 1507860000000,

        "salesOrderName": "JXSO234",

        "refundStatus": "Awaiting approval",

        "notes": "Created from API",

        "disableAccountsSync": true,

        "stockReturned": true,

        "refundLineItems": [

            {

              "itemName": "2013 Gloria GSM 750ml",

              "returnQuantity": 5

            },

            {

              "itemName": "2014 BSE Cabernet Sauvignon 750ml",

              "returnQuantity": 10

            }

          ]

}

You can view the created refunds using the following end points:

All refunds             -     http://<base_api_url>/api/v6/refund/list/

Refund by id        -     http://<base_api_url>/api/v6/sales-orders/<id>

Refund by code   -    http://<base_api_url>/v6/sales-orders/?code=<code>

  1. Query options

You can add these parameters to the above end point to filter out the results:

For more details see the vintrace apiary

  1. Inventory

You can get available stock levels using the Vintrace API.

If you want to view the breakdown of costs associated with the stock items, you need to set the breakoutCosting field to true and the API user needs to have the Can view costs permission.

GET: http://<base_api_url>/api/v6/inventory

  1. Query options

For more details see the  vintrace apiary.

Example : Get Inventory levels for 2012 BSE Merlot 750ml

GET : http://<base_api_url>/api/v6/?breakoutCosting=true&stockType=Single x1&stock=2012 BSE Merlot 750ml

{

        "status": "Success",

        "message": null,

        "inventorySummaries": [

            {

                "date": 1508125708144,

                "dateAsText": "16/10/2017",

                "winery": "King Estate Winery",

                "quantity": 58,

                "committed": 0,

                "onOrder": 0,

                "available": 58,

                "unit": "Single x1",

                "type": "Single x1",

                "code": "2012 BSE Merlot 750ml",

                "name": "2012 BSE Merlot bottle",

                "description": "",

                "lotBatch": null,

                "lotExpiryDate": null,

                "lotExpiryDateAsText": null,

                "lotManufactureDate": null,

                "lotManufactureDateAsText": null,

                "reorderCode": null,

                "location": "Main Warehouse / Main Warehouse",

                "stockCategory": "",

                "price": null,

                "priceAsText": null,

                "taxClass": null,

                "taxState": null,

                "bond": null,

                "sizeRatio": null,

                "finalProducts": "",

                "vintage": null,

                "variety": null,

                "region": null,

                "program": null,

                "owner": "JX2 Winery",

                "unitCost": 11.22,

                "unitCostAsText": "$11.22",

                "totalCost": 651.02,

                "totalCostAsText": "$651.02",

                "fruitCost": 0,

                "fruitCostAsText": "$0.00",

                "bulkCost": 0,

                "bulkCostAsText": "$0.00",

                "additiveCost": 0,

                "additiveCostAsText": "$0.00",

                "operationCost": 0,

                "operationCostAsText": "$0.00",

                "packagingCost": 0,

                "packagingCostAsText": "$0.00",

                "storageCost": 295.92,

                "storageCostAsText": "$295.92",

                "overheadCost": 355.1,

                "overheadCostAsText": "$355.10",

                "freightCost": 0,

                "freightCostAsText": "$0.00",

                "otherCost": 0,

                "otherCostAsText": "$0.00",

                "sku": "10071"

            },

            {

                "date": 1508125708144,

                "dateAsText": "16/10/2017",

                "winery": "JX2 Winery",

                "quantity": 40,

                "committed": 0,

                "onOrder": 0,

                "available": 40,

                "unit": "Single x1",

                "type": "Single x1",

                "code": "2012 BSE Merlot 750ml",

                "name": "2012 BSE Merlot bottle",

                "description": "",

                "lotBatch": null,

                "lotExpiryDate": null,

                "lotExpiryDateAsText": null,

                "lotManufactureDate": null,

                "lotManufactureDateAsText": null,

                "reorderCode": null,

                "location": "Barrel Shed / CELLAR",

                "stockCategory": "",

                "price": null,

                "priceAsText": null,

                "taxClass": null,

                "taxState": null,

                "bond": null,

                "sizeRatio": null,

                "finalProducts": "",

                "vintage": null,

                "variety": null,

                "region": null,

                "program": null,

                "owner": "JX2 Winery",

                "unitCost": 11.22,

                "unitCostAsText": "$11.22",

                "totalCost": 448.98,

                "totalCostAsText": "$448.98",

                "fruitCost": 0,

                "fruitCostAsText": "$0.00",

                "bulkCost": 0,

                "bulkCostAsText": "$0.00",

                "additiveCost": 0,

                "additiveCostAsText": "$0.00",

                "operationCost": 0,

                "operationCostAsText": "$0.00",

                "packagingCost": 0,

                "packagingCostAsText": "$0.00",

                "storageCost": 204.08,

                "storageCostAsText": "$204.08",

                "overheadCost": 244.9,

                "overheadCostAsText": "$244.90",

                "freightCost": 0,

                "freightCostAsText": "$0.00",

                "otherCost": 0,

                "otherCostAsText": "$0.00",

                "sku": "10071"

            }

        ]

}


  1. Customer

Customer refers to the purchaser of your stock in the sales order. A customer can either be an organisation or an individual.

To create a customer as an individual, set the isOrganization field to false. The primeName field is the surname (family name) of the person, and the givenName field is the first (given) name.

To create a customer as an organisation, set the  isOrganization field to true. The primeName field is the organisation’s name and the givenName field is null.

  1. Create/update customer

To update a customer, you must provide the ID of the customer to be updated, otherwise a new customer will be created.

POST

http://<domain_url>/api/v6/party

Field

Type

Description

ID

Integer

If entered updates the party

primeName

String

If party is set as an individual, the surname/family name of the individual. Else, if party is set as organisation, the name of the organisation.

givenName

String

Mandatory if party is set as an individual, the first (given) name of the individual. Else, if party is set as organisation, can be null.

phone

String

Phone number

email

String

Email address

address

Address

 

 

street1

String

Street address line 1

 

street2

String

Street address line 2

 

city

String

City

 

state

String

State

 

postalCode

String

Postal code

 

country

String

Country

isOrganization

Boolean

Set to true if party is an organisation, otherwise, false if party is an individual.

 

Sample create

 {

   "primeName": "Tim",

   "givenName": "Smith",

   "email": "timsmith@abc.com",

   "phone": "(03) 8337 0444 ",

   "address": {

            "street1": "PO Box 5124",

            "street2": null,

            "city": "Napa",

            "state": "CA",

            "postalCode": "94558",

            "country": "USA"

        },

   "isOrganization": false

}

You can view the created customer using the following end point

All customer               -     http://<base_api_url>/api/v6/party/list/

Customer by id        -           http://<base_api_url>/api/v6/party/<id>

Customer by name  -    http://<base_api_url>/v6/party/?name=<name>

  1. Query options