Orders

Fetch orders

The Integration Platform handles connections to multiple remote systems and multiple remote systems can alter a record type. It is important to understand the difference between an one-to-one integration and an integration platform when handling fetching order information.

The order can be updated multiple times and all updates to the order will change the last modified date e.g.:

  • new orderStatus
  • new shippingStatus
  • new shipment
  • new payment event

This described endpoint can be used to fetch all orders, however the parameter modifiedAtOrAfter will limit the response to all orders with a timestamp more or equal the selected timestamp. It is recommended to fetch order changes regularly and handle updates in the integrating system.

Query parameter

modifiedAtOrAfter (Date time)

Request

$ curl \
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/order?modifiedAtOrAfter=2020-09-24T17:23:01Z

Response

Full response omitted for brevity.

[
    {
        "href": "/api/order/00061e1066ab0aca7473627d3d488c86",
        "localId": "00061e1066ab0aca7473627d3d488c86",
        "remoteIdMap": {},
        "remoteRefMap": {},
        "created": "2020-09-10T10:56:10Z",
        "lastModified": "2020-09-25T10:24:02Z",
        ...
    },
    {
        "href": "/api/order/3fb2568eb7e165e34dd311af5550002b",
        "localId": "3fb2568eb7e165e34dd311af5550002b",
        "remoteIdMap": {},
        "remoteRefMap": {},
        "created": "2020-09-10T10:58:10Z",
        "lastModified": "2020-09-25T10:24:02Z",
        ...
    }
]

Order information

Read the section Order to understand the content in the Order. An example of important information is how prices is handled. The field called pricePerUnitExclVat contain the paid price, any discount have already been applied. The discount amount is defined in a separate field. Check the API reference for detailed information.

Note

All orders will be returned if modifiedAtOrAfter is excluded.

Query for specific orders

It is possible to use the query endpoint to find orders that match certain conditions. The endpoint could be used to import orders that have a specific status and that have been changed after a specific time.

An example of this type of query is shown below. All orders that match lastModified>2020-12-22T06:24:57Z and orderStatus="completed" will be returned.

Check the API reference /order/query for more information about available query fields. The fields are documented in the model.

Request

$ curl \
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/order/query \
    -XPOST \
    -d \
    '{
        "filter": {
            "type": "and",
            "subclauses": [
                {
                    "type": "gt",
                    "field": "lastModified",
                    "value": {
                        "type": "datetime",
                        "value": "2020-12-22T06:24:57Z"
                    }
                },
                {
                    "type": "eq",
                    "field": "orderStatus",
                    "value": {
                        "type": "str",
                        "value": "completed"
                    }
                }
            ]
        }
    }'

Response

An array of orders. Full response omitted for brevity.

[
    {
        "localId": "0006463d034d595774bf76d0311a21be",
        "remoteId": "x",
        ...
    },
    {
        "localId": "3fb2568eb7e165e34dd311af5550002b",
        "remoteId": "y",
        ...
    }
]

Create a sales order

Read the section Record types -> Order before continuing.

A sales order is created as an order with the orderType: "sale".

The full content of the order is described in API references Order. Below are some important notes to help when creating and verifying an order.

VatRates/taxes
Test to create an order that contains order rows with different vat rates e.g 25%, 12% … and use the field perUnitTaxes.
Discount
Test to represent an order from a purchase with a percent discount and one with a fixed amount discount. Note that Sharespine handles both types of discounts as amounts. The discount can be added on each orderrow as rowDiscountExclTax OR as a separate row with rowtype “discount”.
orderRows->pricePerUnitExclTax
Note the description of the field: The price PAID per unit without tax. This is after all discounts have been applied and is thus the actual to-pay price. Tip: Create a test order with qty>1, use a discount and verify that all values are correct.
vatType
Read Tax model field descriptions
orderRows->rowType
Test that the correct order row type is used.
source
This section will contain the source of the order i.e the system that created the order. The field code within the source section can be used to add information about “sales channel” in the external system. Use the field code if it is applicable.
Order status
Read Order status fields
Shipment
Shipment contains information about planned/shipped packages. See Add shipment
Payment information
The information is saved as payment events. The information is needed to allow capture of payment from a third party system or for automatic bookkeeping of payment related data. See Add payment information and Payments

Request

$ curl \
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/order \
    -XPOST \
    -d \
    '{
      "orderTime": "2021-05-19T10:10:10Z",
      "customerType": "person",
      "vatType": "DomesticVendorResponsible",
      "currency": "SEK",
      "orderType": "sale",
      "orderNo": "10001",
      "totalSumExclTax": {
        "currency": "SEK",
        "amount": "80.00"
      },
      "totalTax": {
        "currency": "SEK",
        "amount": "20.00"
      },
      "billingAddress": {
        "name": {
          "firstName": "Test",
          "lastName": "Person"
        },
        "street": "Gatan",
        "zipCode": "12345",
        "city": "Staden",
        "country": "SE",
        "phoneNumbers": [
          {
            "type": "mobile",
            "number": "+46701234567"
          }
        ],
        "emailAddress": "test@example.com",
      },
      "shippingAddress": {
        "name": {
          "firstName": "Test",
          "lastName": "Person"
        },
        "street": "Gatan",
        "zipCode": "12345",
        "city": "Staden",
        "country": "SE",
        "phoneNumbers": [
          {
            "type": "mobile",
            "number": "+46701234567"
          }
        ],
        "emailAddress": "test@example.com",
      }
    },
      "orderRows": [
        {
          "rowType": "product",
          "sku": "1",
          "title": "T-Shirt - XS / Blue",
          "qty": "1",
          "pricePerUnitExclTax": {
            "currency": "SEK",
            "amount": "80.00"
          },
          "perUnitTaxes": [
            {
              "taxType": "vat",
              "taxableAmount": {
                "currency": "SEK",
                "amount": "80.00"
              },
              "tax": {
                "currency": "SEK",
                "amount": "20.00"
              }
            }
          ]
        }
      ]
    }'

Update order rows

There are several options to update order rows. Choose the best options for your use case.

  • Update one specific order row by using the endpoints PUT /order/{localId}/orderrow/{orderrowlocalId} or PUT /order/by-remote-id/orderrow/by-remote-id.
  • Update one or more order rows by using the endpoints PUT /order/{localId}/orderrow or PUT /order/by-remote-id/orderrow. Send an array with order rows that should be updated.
    • matchLocalId or matchRemoteId for the order row is required. The id are used to identify order row to update.
    • row should contain the updated data
    • the endpoints above can not be used to add new order rows.
  • Replace all order rows by using the endpoints PUT /order/{localId} or PUT /order/by-remote-id.
    • all existing order rows will be replaced with the order rows send in the request. It is however possible to update the order without affecting the order rows by excluding the orderRows-field from the request.

Find the endpoints at API references - Orders

Add tracking information

A common use case is when an external part need order information to fulfill the order. The order will be fetched from the Integration Platform, processed and shipped to the customer. The external system wants to update the order with tracking information. This article will show an example on how that can be done through the API.

The workflow in this example is:

  1. Fetch the order from the Integration Platform
  2. Handle the order in the external system
  3. Ship the order to the customer
  4. Add a shipment to the order
  5. Update the order status, shipping status

Fetch order

The order should be fetched from the Integration Platform which can be done by the method described in Fetch orders. The response will contain all matching orders, save the localId for each order. The localId can be used in the next call when adding the shipment.

Add a shipment

In this example we will only add a tracking code and a tracking uri. The Integration Platform stores tracking information as a shipment connected to the order. The shipment can be sent to any remote system that have shipment support in the Integration Platform.

Request

$ curl \
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/order/{localId}/shipment \
    -XPOST \
    -d \
    '{
        [
            {
                "trackingCode": "Trackingcode test",
                "trackingUri": "https://tracking.example.com"
            }
        ]
    }'
Note

You can also use /order/by-remote-id/shipment?remoteId={the order remoteId}.

Update status

The order should probably be updated when it has been shipped to the customer. The order can have an order status, payment status and a shipping status. In this example we will update the order status and the shipping status.

The current available status values for orderStatus and shippingStatus can be found in the API reference, check the model for OrderEdit.

$ curl \
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/order/{localId} \
    -XPUT \
    -d \
    '{
        [
            {
                "orderStatus": "complete",
                "shippingStatus": "fully-shipped"
            }
        ]
    }'
Note

You can also use /order/by-remote-id?remoteId={the order remoteId}.

Response

Full response omitted for brevity.

{
    "orderStatus": "complete",
    "shippingStatus": "fully-shipped",
    ...
}

Add payment information

An order contains payment information that includes:

  • Payment method.
  • Payment transaction.
  • Payment transaction events.

Read the section Record types -> Order and Payments before continuing.

Payment Method

A payment method is an entity in the Integration Platform and can be created through the API see API reference. Use an existing payment method or create a new one and save the localId.

Request

$ curl \
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/payment/method \
    -XPOST \
    -d \
    '{
        [
            {
                "remoteId": "checkout_provider",
                "name": "Checkout provider",
                "notes": "Some text"
            }
        ]
    }'

Response

Full response omitted for brevity.

{
    "remoteId": "checkout_provider",
    "name": "Checkout provider",
    "notes": "Some text",
    ...
}

Payment transaction

A payment transaction is started by a prepare event in the Integration Platform and is mandatory. A prepare event could be created when a payment is reserved by the payment provider. A prepare event is added to an order, and it also contains a payment method.

A common transaction event sequence is:

  1. prepare Reserve payment.
  2. payment Capture/finalize payment.
  3. deposit Payout from the PSP.

Another possible transaction sequence is:

  1. prepare Reserve payment.
  2. payment Capture/finalize payment.
  3. deposit Payout from the PSP.
  4. credit Payment to the customer is credited.
  5. refund A refund to the PSP since the payout was done before the credit.

All transaction events after prepare is added by a POST to the endpoint /payment/transaction/{localId}/event/

Create prepared payment transaction

Request

$ curl \
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/order/{localId}/payment \
    -XPOST \
    -d \
    '{
        "type": "prepare",
        "eventTime": "2015-01-02T03:04:05Z",
        "paymentMethodId": "3fb2568eb7e165e34dd311af5550002b",
        "correlationId": "{Unique id for the transaction (created by the payment service provider)}",
        "correlationOrderNo": "string",
        "comment": "string",
        "amount": {
            "currency": "SEK",
            "amount": "100.00"
        },
        "feeExclTax": {
            "currency": "SEK",
            "amount": "4.00"
        },
        "feeTaxes": [
            {
                "taxType": "vat",
                "label": "string",
                "percentage": "25.00",
                "taxableAmount": {
                    "currency": "SEK",
                    "amount": "4.00"
                },
                "tax": {
                    "currency": "SEK",
                    "amount": "1.00"
                }
            }
        ]
    }'
Note

More details can be found in the API reference in the section Payment Transaction -> events.

Add payment event

Request

$ curl \
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/payment/transaction/{localId}/event/ \
    -XPOST \
    -d \
    '{
        "type": "payment",
        "eventTime": "2015-01-02T03:04:05Z",
        "amount": {
            "currency": "SEK",
            "amount": "100.00"
        },
        "feeExclTax": {
            "currency": "SEK",
            "amount": "4.00"
        },
        "feeTaxes": [
            {
                "taxType": "vat",
                "label": "string",
                "percentage": "25.00",
                "taxableAmount": {
                    "currency": "SEK",
                    "amount": "4.00"
                },
                "tax": {
                    "currency": "SEK",
                    "amount": "1.00"
                }
            }
        ]
    }'

Create a return order

Read the section Record types -> Order before continuing.

A return order is created as an order with the orderType: "return" and the field returnedOrder which refer to the original sales order within the Integration Platform.

Note

The field returnedOrder is mandatory for returns.

The example below shows a return of the product T-Shirt - XS / Blue with the pricePerUnitExclTax 80 SEK. The pricePerUnitExclTax can be set to the same value (or lower) as was set on the original sales order.

Request

$ curl \
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/order \
    -XPOST \
    -d \
    '{
      "orderTime": "2021-05-19T10:10:10Z",
      "customerType": "person",
      "currency": "SEK",
      "orderType": "return",
      "orderNo": "10001",
      "returnedOrder": {
        "localId": "0008329ba79e98a8799e5c0d48cc25f9"
      },
      "totalSumExclTax": {
        "currency": "SEK",
        "amount": "80.00"
      },
      "totalTax": {
        "currency": "SEK",
        "amount": "20.00"
      },
      "orderRows": [
        {
          "rowType": "product",
          "sku": "1",
          "title": "T-Shirt - XS / Blue",
          "qty": "1",
          "pricePerUnitExclTax": {
            "currency": "SEK",
            "amount": "80.00"
          },
          "perUnitTaxes": [
            {
              "taxType": "vat",
              "taxableAmount": {
                "currency": "SEK",
                "amount": "80.00"
              },
              "tax": {
                "currency": "SEK",
                "amount": "20.00"
              }
            }
          ]
        }
      ]
    }'

Related information