Order Push API
Summary of Changes: (The purpose of this table is to keep traceability and Product team to highlight the things that were changed into the scope, based on comments or discussions)
Version | Date | Created / Updated | Notes |
---|---|---|---|
v1.0 | 04.04.23 | Bogomil Pavlov | First publish |
v1.1 | 18.05.23 | Bogomil Pavlov | Mapping Amendments |
v1.2 | 05.06.23 | Bogomil Pavlov | Oder Payment Transaction id |
v1.3 | 12.06.23 | Bogomil Pavlov | Mapping Amendments |
v1.4 | 15.06.23 | Bogomil Pavlov | Mapping Amendments |
Including removal of v1.3 in the scope below |
The purpose of this document is to describe how Very will create orders in Hemi.
The flow of creating orders is in the opposite way and Very will be creating order directly into our system. Thus we have to build a listener which accept orders in specific format.
”The Order Push API” allows a supplier to configure a dropship URL that will receive order details for any new orders created by retailers.
Order details are sent to the URL via a simple JSON POST
request.
Additionally, a X-CustomGateway-Hmac
header is also sent as part of the request. This header can be used to verify that the request has originated from Kornit X.
Setup
To receive order pushes, a supplier must enable the "Generic API" supplier integration against the relevant dropshipping account in the Kornit X platform.
Once the integration has been enabled, a push URL defined and changes saved, a HMAC key will be automatically generated.
Verifying the HMAC Header
Whilst optional, this step is highly recommended for security.
For each push request, a HMAC message digest can be calculated using the SHA256 algorithm with the request body as the input and the HMAC key displayed in the Generic API settings page.
The calculated HMAC message digest should match the value of the requests's X-CustomGateway-Hmac
header.
If the values do not match then you should reject the push request.
Sample way of doing this:
$hmac = hash_hmac('sha256', file_get_contents('php://stdin'), $key);
if(!hash_equals($hmac, getHeader('X-CustomGateway-Hmac')))
{
throw new \Exception('HMAC mismatch');
}
”
Sample payload:
{
"id": 48292893,
"company_ref_id": 123456,
"secondary_company_ref_id": "789012",
"ref": "BA5081446450F3FE",
"status": 1,
"shipping_company": "",
"shipping_address_1": "123 Test Street",
"shipping_address_2": "",
"shipping_address_3": "",
"shipping_address_4": "Test",
"shipping_address_5": "",
"shipping_postcode": "SK10 2XR",
"shipping_country": "United Kingdom",
"shipping_country_code": "GB",
"billing_company": "",
"billing_address_1": "",
"billing_address_2": "",
"billing_address_3": "",
"billing_address_4": "",
"billing_address_5": "",
"billing_postcode": "",
"billing_country": "United Kingdom",
"customer_name": "Paul Test",
"customer_telephone": "",
"customer_telephone_mobile": "",
"sale_datetime": "2023-05-02 11:14:12",
"external_ref": "L281223899999-L8-PH",
"has_been_completed": false,
"completion_datetime": "0000-00-00 00:00:00",
"has_pdf_been_queued": false,
"has_pdf_been_completed": false,
"shipping_method": "Next Day",
"customer_email": "paul.heseltine@kornit.com",
"shipping_carrier": "DPD",
"shipping_tracking": "",
"shipping_note_url": "",
"payment_trans_id": "",
"payment_type": "",
"has_initial_confirmation_email_been_sent": false,
"has_shipping_confirmation_email_been_sent": false,
"creation_datetime": "2023-05-02 11:29:02",
"additional_info": "",
"has_error": false,
"error_message": "",
"required_dispatch_date": "0000-00-00",
"is_status_callback_pending": false,
"stock_request_id": 0,
"status_callback_attempts": 0,
"status_callback_next_retry": "0000-00-00 00:00:00",
"consolidate": false,
"has_been_invoiced": false,
"billing_customer_name": "",
"billing_customer_email": "",
"billing_customer_telephone": "",
"shipping_price": 6,
"shipping_price_inc_tax": 0,
"shipping_tax_rate": 0,
"is_urgent": false,
"tag": "",
"pos_user_id": null,
"coupon_code": "",
"currency_code": null,
"is_free_of_charge": false,
"status_name": "Received",
"company_external_ref": "",
"items": [
{
"id": 85632673,
"sale_vat_rate": 0.2,
"external_ref": "POS-EF8FE5",
"ref": "8D2BD93C6450F3FE",
"order_id": 48292893,
"sku": "11508",
"mapped_sku": "11508",
"description": "Slim Fit White Shirt",
"colour": "",
"size": "",
"quantity": 2,
"type": 4,
"print_job_id": 0,
"print_job_promise_ref": "",
"external_url": "",
"external_thumbnail_url": "",
"status": 1,
"print_on_demand_ref": "",
"plain_stock_item_ref": "",
"license": "",
"license_percentage": "",
"unit_sale_price": 69.99,
"unit_sale_price_inc_tax": 0,
"unit_cost_price": 12.48,
"shipping_price": 0,
"shipping_price_inc_tax": 3,
"bundle_ref": "",
"textual_product_id": "11791111",
"product_variant_id": null,
"quantity_batched": 0,
"quantity_dispatched": 0,
"stock_request_id": null,
"artwork_barcode": "",
"quantity_consolidated": 0,
"product_state_id": null,
"status_name": "Received",
"attributes": [],
"assets": []
},
{
"id": 85632674,
"sale_vat_rate": 0.2,
"external_ref": "POS-961B06",
"ref": "46C958316450F3FE",
"order_id": 48292893,
"sku": "11655",
"mapped_sku": "11655",
"description": "Tailored Fit White Shirt",
"colour": "",
"size": "",
"quantity": 1,
"type": 4,
"print_job_id": 0,
"print_job_promise_ref": "",
"external_url": "",
"external_thumbnail_url": "",
"status": 1,
"print_on_demand_ref": "",
"plain_stock_item_ref": "",
"license": "",
"license_percentage": "",
"unit_sale_price": 59.99,
"unit_sale_price_inc_tax": 0,
"unit_cost_price": 10.99,
"shipping_price": 0,
"shipping_price_inc_tax": 0,
"bundle_ref": "",
"textual_product_id": "11792222",
"product_variant_id": null,
"quantity_batched": 0,
"quantity_dispatched": 0,
"stock_request_id": null,
"artwork_barcode": "",
"quantity_consolidated": 0,
"product_state_id": null,
"status_name": "Received",
"attributes": [],
"assets": []
}
],
"pdfs": [
{
"id": 32511879,
"order_id": 48292893,
"type": 1,
"url": "https://s3-eu-west-1.amazonaws.com/xxx.pdf",
"ref": "mjjkzj7fdf6trmwwx0jf",
"is_outdated": false
}
],
"shipments": []
}
Mapping: N/A means we do not map this field anywhere in Hemi. Please note not all fields may be pushed from KornitX.
Very Field | Hemi Field | Comment | ||
---|---|---|---|---|
id |
Orders > Marketplace Order ID | We want to include validation and return them an error if Orders > Marketplace Order ID already exist in our system. | ||
company_ref_id |
N/A | |||
secondary_company_ref_id |
N/A | |||
ref |
N/A | |||
status |
N/A | |||
shipping_company |
Orders > Company Name | Under Shipping Details tab | ||
shipping_address_1 |
Orders > Shipping Street 1 | (v1.1)If nothing is populated in shipping_address_1 but have data in shipping_address_2 , we want to move it to Orders > Shipping Street 1 |
||
shipping_address_2 |
Orders > Shipping Street 2 | |||
shipping_address_3 |
Orders > Shipping Street 2 | If this is populated we want to concatenate it with Orders > Shipping Street 2 | ||
shipping_address_4 |
Orders > Shipping City | |||
shipping_address_5 |
Orders > Shipping State Province | |||
shipping_postcode |
Orders > Shipping Postal Code | |||
shipping_country_code |
Orders > Shipping Country Code | ISO 3166-1 alpha-2 country code. | ||
shipping_country |
Orders > Shipping Country Name | |||
billing_company |
Orders > Company Name | Under Billing Details tab | ||
billing_address_1 |
Orders > Billing Street 1 | (v1.1)If nothing is populated in billing_address_1 but have data in billing_address_2 , we want to move it to Orders > Billing Street 1 |
||
billing_address_2 |
Orders > Billing Street 2 | |||
billing_address_3 |
Orders > Billing Street 2 | If this is populated we want to concatenate it with Orders > Billing Street 2 | ||
billing_address_4 |
Orders > Billing City Name | |||
billing_address_5 |
Orders > Billing State Province | |||
billing_postcode |
Orders > Billing Postal Code | |||
billing_country |
Orders > Billing Country Name | |||
billing_country_code |
Orders > Billing Country Code | |||
customer_name |
Orders > Shipping Buyer Name | |||
customer_telephone |
Orders > Shipping Phone | This is used only if we are missing the customer_telephone_mobile |
||
customer_telephone_mobile |
Orders > Shipping Phone | This on is with priority and if we receive both we want to store only this | ||
sale_datetime |
N/A | |||
external_ref |
Orders > Selling Manager SalesRecordNumber | |||
has_been_completed |
N/A | |||
completion_datetime |
N/A | |||
has_pdf_been_queued |
N/A | |||
has_pdf_been_completed |
N/A | |||
shipping_method |
Orders > Shipping Service | |||
customer_email |
Orders > Buyer mail | |||
shipping_carrier |
Orders > Shipping Carrier | |||
shipping_tracking |
Orders > Shipping Track Number | |||
shipping_note_url |
Orders > Shipping Tracking URL | |||
payment_trans_id |
Orders > External Trans ID | |||
payment_type |
Orders > Order Payment Method | |||
has_initial_confirmation_email_been_sent |
N/A | |||
has_shipping_confirmation_email_been_sent |
N/A | |||
creation_datetime |
Orders > Order Created Time | Please note we want to store unix. Format: 2023-05-02 11:29:02 |
||
additional_info |
Orders > Note | |||
has_error |
N/A | |||
error_message |
N/A | |||
required_dispatch_date |
Orders > Ship By Date | Please note we want to store unix. Format 2023-12-01 |
||
is_status_callback_pending |
N/A | |||
stock_request_id |
N/A | |||
status_callback_attempts |
N/A | |||
status_callback_next_retry |
N/A | |||
consolidate |
N/A | |||
has_been_invoiced |
N/A | |||
billing_customer_name |
Orders > Billing Name | |||
billing_customer_email |
N/A | |||
billing_customer_telephone |
Orders > Billing Phone | |||
shipping_price |
Orders > Total Shipping Marketplace VAT | We want to calculate shipping_price_inc_tax - shipping_price in order to get the correct Total VAT shipping price. |
||
shipping_price_inc_tax |
Orders > Shipping Service Cost | |||
shipping_tax_rate |
N/A | |||
is_urgent |
N/A | |||
tag |
N/A | |||
pos_user_id |
N/A | |||
coupon_code |
Orders > Discount Code | |||
currency_code |
Orders > Order Currency | If missing we want to get it from Account > Exchange Rate Calculator Currency | ||
is_free_of_charge |
N/A | |||
status_name |
Orders > Marketplace status | |||
company_external_ref |
N/A | |||
items |
||||
id |
Product In Order > Item Order Line ID | Product In Order > Item Order Line ID | ||
type |
N/A | |||
sale_vat_rate |
Product In Order > Marketplace VAT Percent | |||
external_ref |
N/A | |||
ref |
Product In Order > Chanel Item ID | |||
order_id |
N/A | |||
colour |
Product In Order > Item Variations | (v1.1)Fields here should be combined in the specific field type which is Table with two columns | ||
size |
Product In Order > Item Variations | |||
mapped_sku |
N/A | |||
sku |
Product In Order > SKU | |||
description |
N/A | |||
quantity |
Product In Order > Quantity | |||
print_job_id |
N/A | |||
print_job_promise_ref |
N/A | |||
external_url |
N/A | |||
external_thumbnail_url |
N/A | |||
status |
N/A | |||
print_on_demand_ref |
N/A | |||
plain_stock_item_ref |
N/A | |||
license |
N/A | |||
license_percentage |
N/A | |||
unit_sale_price |
Product In Order >Item Price | (v1.4) The only price we will receive will be unit_sale_price however we still may receive and orders without unit_sale_price and we want to treat them as completed and set the status as “Ready For Shipping“ |
||
unit_sale_price_inc_tax |
N/A | |||
unit_cost_price |
Product In Order >Item Original Price | |||
shipping_price |
Product In Order >Marketplace VAT Item Shipping Cost | We want to calculate shipping_price_inc_tax - shipping_price in order to get the VAT for the shipping cost |
||
shipping_price_inc_tax |
Product In Order >Item Shipping Cost | |||
bundle_ref |
N/A | |||
textual_product_id |
N/A | |||
product_variant_id |
N/A | |||
quantity_batched |
N/A | |||
quantity_dispatched |
N/A | |||
stock_request_id |
N/A | |||
artwork_barcode |
N/A | |||
quantity_consolidated |
N/A | |||
product_state_id |
N/A | |||
status_name |
Product In Order >Status | |||
attributes |
N/A | |||
assets |
N/A | |||
pdfs |
||||
id |
N/A | |||
order_id |
N/A | |||
type |
N/A | |||
url |
Orders Very > Dispatch Note | New Field. | ||
ref |
N/A | |||
is_outdated |
N/A | |||
shipments |
N/A |
Since their payload is limited we have to make sure any missing information which is not provided by Very and is mandatory for Hemi to be filled.
Hemi Field | Comment |
---|---|
Orders > Account | Based on the url which we will provide we will know for which account is the actual order. |
(v1.1)Orders > Status | Every order they are pushing to Hemi will e paid and with status “Ready For Shipping“ |
Orders > Оrder Тotal Аmount | Based on the item prices we need to calculate the total amount |
Orders > Оrder Subtotal Аmount | Based on the item prices we need to calculate the total amount - shipping cost |
Product in Order > Account | (v1.1)Based on the sku and the order account we have to map the correct correct Account Id from the order |
Product in Order > Seller | Based on the sku and the order account we have to map the correct Product Account and get the correct Seller Id |
Product in Order > Item Title | Based on the sku and the order account we have to map the correct Product Account and get the correct Title |
Order Item Line >Line ID | For each quantity we have to store additional row as per standard. |
Order Payment > Transaction ID | (v1.2)Same as Orders >External Trans ID (If empty use Orders > Marketplace Order ID) |
Order Payment > Payment Date | Same as Orders > Order Created Time |
Order Payment > Total Amount | Same as Orders > Оrder Тotal Аmount |
Order Payment > Type | “Payment“ |
Order Payment > Status | “Completed“ all orders we are receiving will be paid |
Also the same is the case with the validations and if we receive and order with missing or duplicate:
Hemi Field
Orders > Marketplace Order ID
Product In Order > Item Order Line ID
Orders > External Trans ID
We want to return and error and do not allow to create the order.
If any of the mandatory information as per abstraction is missing we want to set the Orders > Status = Incomplete
<v1.5> We also need to have a grace period of 30 minutes in which we keep the order on ‘Pending’ status