Receive Orders

Receive orders placed by your customers via Apicbase

Requirements

Before getting started, please verify that you meet the following requirements:

  1. The customer must have an assortment in Apicbase platform maintained either by:
    1. The supplier: Via the assortment integration.
    2. The customer: Please make sure the customer uses the same article numbers (the unique code to identify articles) as you use in your system. This is the code we'll send in the orders.
  2. Please review the topics below and ensure that you can support automation either through webhooks or by polling our API endpoint.

Integration Methods

Webhooks

Webhooks are the most recommended integration method for ordering, provided you can provide us with a HTTP/S endpoint where the orders can be posted. If you have such an endpoint, please contact [email protected] with the URL, and we'll set it up for you.

This approach has several advantages:

  1. It's significantly simpler compared to the alternative. All you need to do is create a script that will be listening at the endpoint configured to the webhook to process new orders and return an appropriate HTTP status code.
  2. As soon as an order is placed on the Apicbase platform, the orders are immediately sent to the configured endpoint.
  3. Orders placed on Apicbase and rejected by the webhook endpoint (any response code different than 2XX) will immediately display an error to the customer at the end of the process. The customer must place the order again manually to complete the process, which avoids the need of contacting the customer about orders that can't be fulfilled. That's especially useful for orders with the HTTP response status code 4XX.

However, this approach requires more careful error handling on your part.

If an order cannot be placed because the endpoint that receives it is unavailable (e.g., due to bugs or server unavailability), it will not be automatically retried. Consequently, the customer will be unable to place the order until the issue is resolved.

If an order fails to be placed due to errors on our side or on the webhook's endpoint (the request generates any response code other than 2XX), an error message will be displayed to the customer. The order status will remain as in progress (i.e., not sent), and the customer will have to retry sending it manually after the issue is fixed. Therefore, it's important to understand that failed orders will not be automatically retried and will clearly be shown as not sent to the customer.

❗️

A note about security.

To ensure the security of these requests, each request from Apicbase is signed with an X-APIC-WEBHOOK-SIGNATURE header key. It is highly recommended that the supplier uses this value to verify if the payload being received is indeed sent by Apicbase.

This verification requires using the client secret and the received payload to generate a HMAC-SHA256 Hexdigest value. By default, the client secret value is the same one used to generate new tokens, but it's also possible to use a different unique key that is only used to encode this header. Just let us know, and we can arrange this for you.

Please also ensure that the verification is performed using the raw request data content or that the content has ASCII encoding. Otherwise, your application may alter the request data slightly (for instance, for characters like á, é) and the verification will fail.

Here's a code snippet with some sample Python code that validates the signature header:

import json
from hmac import HMAC

def endpoint(request):
    signature = request.headers["X-APIC-WEBHOOK-SIGNATURE"]
    
    result = HMAC(
        key="<your_client_secret>",
        msg=json.dumps(request.data).encode(),
        digestmod="sha256"
    ).hexdigest()
    
    if signature != result:
        return Response("Incorrect signature", status_code=403)

API Endpoint

Using our API to poll newly placed orders is an alternative to the webhook approach. The JSON object structure sent in the response is identical to the one sent to the webhook. More information about it can be found in the endpoint reference page.

This approach can provide a useful alternative if these are points of concern:

  1. You don't need to immediately process newly placed orders. There's some flexibility in when you will parse and process new orders.
  2. You need a more robust security scheme around the sending of orders. The API endpoint uses our API's standard OAuth2 authentication.
  3. You want to avoid that orders get rejected due to errors on your side. As mentioned in the webhook section, orders placed by customers will fail if we receive any error response (any response code other than 2XX) from the webhook endpoint. Therefore, the API is useful for 5XX errors, as orders can be processed retroactively once the issue is resolved.

However, there are also some drawbacks to this approach:

It is significantly more complex than using a webhook, because you must:

  1. Keep track of which orders were already processed from our list endpoint;
  2. Periodically call our API endpoint to get new orders, taking into account our rate limits.

When a customer places an order in Apicbase, its status is immediately updated to ORDERED (indicating it has been sent to the supplier). This status cannot be rolled back to IN PROGRESS.

However, the webhook approach updates the order status only after receiving a successful response from the linked endpoint.

The script at the webhook can perform validation steps to ensure the order can be received before sending this successful response. In contrast, the API approach does not allow any validation steps before an order immediately progresses to the ORDERED state. You cannot control the state of an invalid order, and orders that are later rejected must be communicated directly to the customer.

Data Structure

Regardless of the method used to manage orders, the purchase order data will remain the same, presented as a JSON object with the following structure:

{
  "id": string, -> Apicbase internal Purchase Order ID
  "order_number": string,
  "status": "ORDERED", -> fixed value
  "ordered_on": datetime,
  "owned_by": {"username": string} | null,
  "order_remarks": string | null,
  "packages": [
    {
      "stock_item": {
        "name": string
      },
      "supplier_package": {
        "supplier_article_number": string,
        "theoretical_price_per_package": string
      },
      "quantity_ordered": integer,
      "total_theoretical_price": string
    }
  ],
  "expected_delivery_date": datetime | null,
  "theoretical_price": string,
  "supplier_customer_number": string
}

Here are the most relevant fields in the JSON above:

  • order_number: It's a unique identifier as the id field but also displayed to the customers in Apicbase platform, which makes it important for debugging, tracking orders and to place in invoices if possible.
  • expected_delivery_date: When the customer expects to receive the order.
  • supplier_customer_number: Unique customer location identifier arbitrarily defined by the supplier. Apicbase expects to receive this number to setup the customer locations before the customer starts placing orders.
  • packages:
    • supplier_package.supplier_article_number: Unique identifier used by the supplier to identify the article.
    • quantity_ordered: Amount of articles ordered.

Testing

Please check our Sandobx Account guide in order to test your ordering integration.