Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Table of Contents
includeindentclass
minLevel1
maxLevel64
outlinefalse
styledefault
excludeWhat is a webhook?|Implementing a Webhook in OneStock
typelist
printabletrue

1. Configure your site for webhooks

...

Expand
titleCopy paste sample 👇
Code Block
languagejson
{
  "retry_intervals": [
    30,
    60,
    120,
    240,
    480,
    840
  ],
  "retries_until_failure": 3,
  "on_failure": {
    "contact_emails": [
      "email@company.com"
    ],
    "contact_mobiles": [],
    "sms_notification_name": "",
    "email_notification_name": "webhook_failure"
  },
  "on_deactivation": {
    "contact_emails": [
      "email@company.com"
    ],
    "contact_mobiles": [],
    "sms_notification_name": "",
    "email_notification_name": "webhook_deactivation"
  },
  "on_failure_recovered": {
    "contact_emails": [
      "email@company.com"
    ],
    "contact_mobiles": [],
    "sms_notification_name": "",
    "email_notification_name": "webhook_failure_recovered"
  }
}

...

3. Subscribe your webhook to a topic

In order to subscribe To listen to OneStock events you will subcribe your webhook to a topic, add the topic to the code, as shown in the example below on lines 5 and 6.

...

languagejson

...

. We distinguish to types of topics, standard and custom. Standard topics work out of the box, you just need to sucribe your webhook to one of them and you will start receving all events that go through the topic event stream. Custom topics need slightly more configuration and allow you to listen to specific events that you will trigger trough your workflow.

Standard topics

1. Subcribe a webhook to a standard topic

To listent to topics, you simply need to subscribe a webhook to one or multiple topics, through a

POST /webhooks call.

POST /webhooks

Code Block
{
  "site_id": "MySiteID",
  "token":"token",
  "webhook": {
    "hash_key": "personnal_hash_key",
    "http_method": "POST",
    "status": "enabled",
    "topics": [
      "order_state_changed",
      "parcel_state_changed",
      "stockline_item_importgroup_errorstate_occurredchanged"
    ],
    "url": "https://myWebhookURL" //you can generate a disposbel one at https://webhook.site/
  }
}

Information about the expected responses can be found in our documentation here.

Standard topics

This is Following a list of all the events topics we currently sendsupport. We may add more at any time, so in developing and maintaining your code, you should not assume that only these topics exist.

Topic

Displayed Name

Description

Message structure

buffer_import_completed

Buffer Import Completed

Notifies when an async buffer import using API or file is completed

buffer_import_completed

Code Block
import_id: string
status: string

Status
colourYellow
title12.4

buffer_import_error_occurred

Buffer Import Error Occurred

Notifies when a synchronous buffer import using API POST method fails

buffer_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

Status
colourYellow
title12.4

async_buffer_import_error_occurred

Asynchronous Buffer Import Error Occurred

Notifies when an asynchronous buffer import fails

async_buffer_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

… full list bellow

Expand
titleFull list of standard topics

Topic

Displayed Name

Description

Message structure

buffer_import_completed

Buffer Import Completed

Notifies when an async buffer import using API or file is completed

buffer_import_completed

Code Block
import_id: string
status: string

Status
colourYellow
title12.4

buffer_import_error_occurred

Buffer Import Error Occurred

Notifies when a synchronous buffer import using API POST method fails

buffer_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

Status
colourYellow
title12.4

async_buffer_import_error_occurred

Asynchronous Buffer Import Error Occurred

Notifies when an asynchronous buffer import fails

async_buffer_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

customer_import_completed

Customer Import Completed

Notifies when an async customer import using API or file is completed

customer_import_completed

Code Block
import_id: string
status: string

Status
colourYellow
title12.4

customer_import_error_occurred

Customer Import Error Occurred

Notifies when a synchronous customer import using API POST method fails

customer_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

Status
colourYellow
title12.4

async_customer_import_error_occurred

Asynchronous Customer Import Error Occurred

Notifies when a asynchronous customer import fails

async_customer_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

transfer_import_completed

Transfer Import Completed

Notifies when an async transfer import using API or file is completed

transfer_import_completed

Code Block
import_id: string
status: string

transfer_import_error_occurred

Transfer Import Error Occurred

Notifies when a synchronous transfer import using API POST method fails

transfer_import_error_occurred

Code Block
error: string
invalid_transfers: string
request_body: string
date: int64

Status
colourYellow
title12.4

async_customer_import_error_occurred

Asynchronous Transfer Import Error Occurred

Notifies when an asynchronous transfer import fails

async_transfer_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

stock_import_completed

Stock Import Completed

Notifies when an async stock import using API or file is completed

stock_import_completed

Code Block
import_id: string
status: string

stock_import_error_occurred

Stock Import Error Occurred

Notifies when a synchronous stock import using API POST method fails

stock_import_error_occurred

Code Block
error: string
error_content: string
import_id: string
request_body: string
date: int64

Status
colourYellow
title12.4

async_stock_import_error_occurred

Asynchronous Stock Import Error Occurred

Notifies when an asynchronous stock import fails

async_stock_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

line_item_group_state_changed

Line Item Group State Change

Notifies of a state change for line item groups

line_item_group_state_changed

Code Block
order_id: string
date: int64
old_state: string
new_state: string
order_item_id: string
index_ranges: indexRanges
quantity: int64

 

order_state_changed

Order State Change

Notifies of a state change for orders

order_state_changed

Code Block
order_id: string
date: int64
old_state: string
new_state: string

 

parcel_state_changed

Parcel State Change

Notifies of a state change for parcels

parcel_state_changed

Code Block
order_id: string
date: int64
old_state: string
new_state: string
parcel_id: string

 

entity_updated

Entity Update

Notifies of OMS entities information changes (parcels, line item groups and orders) POP (endpoint_orders, containers, piece_groups) and RM (return_parcels, and return_line_item_groups)

line_item_group_entity_updated, order_entity_updated, parcel_entity_updated

Code Block
site_id: string
entity_id: string
entity_type: string
date: int64
diff: map[string]any

orchestration_rules_changed

Orchestration Rules Changed

Allows triggering of preparation order on time.

When there is an orchestration rule change with a warehouse custom claim action triggered, line item groups are retrieved and a preparation order is sent to the warehouse.

orchestration_rules_changed

Code Block
site_id: string
order_id: string
ruleset_id: string
from: string
to: string
custom_actions: []
    action: string
    rule_index: string
    line_item_index_ranges: indexRange
rules_over: string

 

candidates_added

Candidates Added

Notifies that an endpoint is candidate for an order.

candidates_added

Code Block
site_id: string
order_id: string
endpoint_ids: []string

 

candidates_removed

Candidates Removed

Notifies when an endpoint is no longer candidate for an order.

candidates_removed

Code Block
site_id: string
order_id: string
endpoint_ids: []string

 

rules_over

Status
colourRed
titleBefore 12.4

orchestration_rules_over

Status
colourYellow
title12.4

Rules Over (custom notification)

Notifies of a rules over transition for an order.

orchestration_rules_over

Status
colourYellow
title12.4
(new version more accurate than rules_over)

Code Block
site_id: string
order_id: string
ruleset_id: string 
line_item_index_ranges: IndexRanges

rules_over

Code Block
site_id: string
order_id: string
ruleset_id: string 

back_from_rules_over

Code Block
site_id: string
order_id: string
ruleset_id: string 

 

item_import_completed

Item Import Completed

Notifies of a completed item import

item_import_completed

Code Block
import_id: string
status: string

Status
colourYellow
title12.4

item_import_error_occurred

Item Import Error Occurred

Notifies when a synchronous item import using API POST method fails

item_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

Status
colourYellow
title12.4

async_item_import_error_occurred

Asynchronous Item Import Error Occurred

Notifies when an asynchronous item import fails

async_item_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

psp_error_occurred

Payment Error

Notifies of errors during payment treatment

psp_error_occurred

Code Block
psp: string
request_route: string
request_body: string
response_body: string

container_state_changed

operator_state_changed

endpoint_order_state_changed

piece_group_state_changed

Order Preparation Entity Change

Notifies of order preparation entity state changes (creation, update, removal)

  • container_state_changed, operator_state_changed, endpoint_order_state_changedand piece_group_state_changed

Code Block
entity_id string
entity_type string
site_id string
date string
old_state string
new_state string

return_parcel_created

Return Parcel Creation

Notifies of the creation of a return parcel

return_parcel_created :

Code Block
languageyaml
order_id: string
id: string
user_id: string
creation_date: int64
return_note_id: string
document_id: string
last_update: int64
returned_line_items: []
  creation_date: string
  id: string
  last_update: string
  reason: string
  receiver_comment: string
  return_condition: string
  sender_comment: string
  item_id: string
  state: string
information: map[string]any
state: string
delivery: 
  origin:
    address:
    endpoint_id: string
  destination:
    address:
      id: string
      city: string
      contact:
        title: string
        first_name: string
        last_name: string
        company_name: string
        phone_number: string
        mobile_number: string
        email: string
      coordinates:
        lon: float64
        lat: float64
      information: map[string]string
      lines: []string
      regions: map[string]
        name: string
        code: string
      zip_code: string
    endpoint_id: string
  carrier:
    name: string
    option: string
    tracking_code: string
    tracking_link: string
    information: map[string]any

return_parcel_created@v3 :

Code Block
languageyaml
documents: map[string]string
order_id: string
id: string
user_id: string
creation_date: int64
last_update: int64
return_line_item_groups: []
  id: string
  order_item_id: string
  creation_date: int64
  last_update: int64
  reason: string
  receiver_comment: string
  return_condition: string
  sender_comment: string
  quantity: int64
  line_item_index_ranges: IndexRanges
  item_id: string
  state: string
information: map[string]any
state: string
delivery:
  origin:
    address:
    endpoint_id: string
  destination:
    address:
      id: string
      city: string
      contact:
        title: string
        first_name: string
        last_name: string
        company_name: string
        phone_number: string
        mobile_number: string
        email: string
      coordinates:
        lon: float64
        lat: float64
      information: map[string]string
      lines: []string
      regions: map[string]
        name: string
        code: string
      zip_code: string
    endpoint_id: string
  carrier:
    name: string
    option: string
    tracking_code: string
    tracking_link: string
    information: map[string]any
shipment:
  id: string
  document_id: string
  tracking_code: string
  tracking_link: string
  transporter: string
  carrier_data: string

 

return_line_item_group_state_changed

return_parcel_state_changed

 

Notifies of a state change for a return return_line_item_group or return_parcel

return_line_item_group_state_changed and return_parcel_state_changed

Code Block
languageyaml
entity_id: string
entity_type: string
site_id: string
date: int64
old_state: string
new_state: string

 

line_items_reservations_updated

Line Items Reservations Update

Notifies of a reservation update on a line item group (global reservation to endpoint reservation, future stock to on hand, endpoint reservation removal)

line_items_reservations_updated

Code Block
languageyaml
added_reservations: []
    id: string
    order_id: string
    sales_channel: string
    global: string
    line_item_index_ranges: index_ranges
    quantity: int64
    item_id: string
    endpoint_id: string
    eta_start: int64
    eta_end: int64
    stock_type: string
    purchase_order_number: string
    remaining_line_item_index_ranges: index_ranges
removed_reservations: []
    id: string
    order_id: string
    sales_channel: string
    global: string
    line_item_index_ranges: index_ranges
    quantity: int64
    item_id: string
    endpoint_id: string
    eta_start: int64
    eta_end: int64
    stock_type: string
    purchase_order_number: string
    remaining_line_item_index_ranges: index_ranges

 

stock_coverage_import_completed

Stock Coverage Import Completed

Notifies of a completed stock coverage import

stock_coverage_import_completed

Code Block
import_id: string
status: string

Status
colourYellow
title12.4

stock_coverage_import_error_occurred

Stock Coverage Import Error Occurred

Notifies when a synchronous stock coverage import using API POST method fails

stock_coverage_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

Status
colourYellow
title12.4

async_stock_coverage_import_error_occurred

Asynchronous Stock Coverage Import Error Occurred

Notifies when an asynchronous stock coverage import fails

async_stock_coverage_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

stock_disposition_import_completed

Stock Disposition Import Completed

Notifies of a completed stock disposition import

stock_disposition_import_completed

Code Block
import_id: string
status: string

Status
colourYellow
title12.4

stock_disposition_import_error_occurred

Stock Disposition Import Error Occurred

Notifies when a synchronous stock disposition import using API POST method fails

stock_disposition_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

Status
colourYellow
title12.4

async_stock_disposition_import_error_occurred

Asynchronous Stock Disposition Import Error Occurred

Notifies when an asynchronous stock disposition import fails

async_stock_disposition_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

endpoint_import_completed

Endpoint Import Completed

Notifies of a completed stock import

endpoint_import_completed

Code Block
import_id: string
status: string

Status
colourYellow
title12.4

endpoint_import_error_occurred

Endpoint Import Error Occurred

Notifies when a synchronous endpoint import using API POST method fails

endpoint_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

Status
colourYellow
title12.4

async_endpoint_import_error_occurred

Asynchronous Endpoint Import Error Occurred

Notifies when an asynchronous endpoint import fails

async_endpoint_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

user_import_completed

User Import Completed

Notifies of a completed user import

user_import_completed

Code Block
import_id: string
status: string

Status
colourYellow
title12.4

user_import_error_occurred

User Import Error Occurred

Notifies when a synchronous user import using API POST method fails

user_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

Status
colourYellow
title12.4

async_user_import_error_occurred

Asynchronous User Import Error Occurred

Notifies when an asynchronous user import fails

async_user_import_error_occurred

Code Block
import_id?: string
errors: []
  entity_id?: string
  message: string
date: int64

carrier_error_occurred

Carrier Error

Relays of errors during carrier communication

carrier_error_occurred

Code Block
carrier: string
request_route: string
request_body: string
response_body: string

tracking_link_created

 

Notifies of the creation of a tracking link

tracking_link_created

Code Block
carrier: string
tracking_link: string

shipment_created

 

Notifies of the creation of a shipment

shipment_created

Code Block
languageyaml
carrier: string
endpoint_id: string
order_id: string
parcel_id: string
shipment_id: string
user_id: string

stock_export_completed

Stock Export Completed

Notifies the completion of a stock export by file (SFTP)

Code Block
export_id string
file_job_id string
exported_lines_count int64

1. Subcribe a webhook to a standard topic

To listent to topics, you simply need to subscribe a webhook to one or multiple topics, through a

POST /webhooks call.

POST /webhooks

...

2. Test that all works correctly

To do so, you can simply create a disposabel webhook endpoint going to https://webhook.site/ and use it as the url of your topic (by clicking on edit you can change the response code do 202, only 100 webhook receptions are allowed for free). In the case of our example, when a parcel transitions from newbagged , as when bagged in the Store App, we should receive a body as the following

Code Block
{
  "order_id": "MySiteIDDV00000007_MC",
  "tokendate":"token" 1727862652,
  "webhook": {
    "hash_keyold_state": "personnal_hash_keynew",
 
  "httpnew_methodstate": "POSTbagged",
 
  "statusparcel_id": "enabled66fd147ab4fefe10957e4a1d",
    "topics": [
      "order_state_changed",
      "parcel_state_changed",
      "line_item_group_state_changed"
    ],
    "url": "https://myWebhookURL" //you can generate a disposbel one at https://webhook.site/
  }
}

2. Test that all works correctly

To do so, you can simply create a disposabel webhook endpoint going to https://webhook.site/ and use it as the url of your topic (by clicking on edit you can change the response code do 202, only 100 webhook receptions are allowed for free). In the case of our example, when a parcel transitions from newbagged , as when bagged in the Store App, we should receive a body as the following

Code Block
{
  "order_id": "DV00000007_MC",
  "date": 1727862652,
  "old_state": "new",
  "new_state": "bagged",
  "parcel_id": "66fd147ab4fefe10957e4a1d"
}

...

Custom topics

If the event you wish to subscribe to is not listed above you can create a custom topic. The custom topic can either notify based on an existing OneStock events, or based on an event triggered in the workflow.

Custom topics can be created via API, or via the Back Office Configuration screens.

1. Create a custom notification

Go to Configuration > Outbound Messages > Notifications, and add a custom notification. Base yourself on the following code example and tailor it to your need by modifing the id and the topic id. Leave the rest unchanged.

Code Block
"email_sent_to_client":{ //notification id, we will reference it in the workflow
  "media":{
}

...

Custom topics

If the event you wish to subscribe to is not listed above you can create a custom topic. The custom topic can either notify based on an existing OneStock events, or based on an event triggered in the workflow.

Custom topics can be created via API, or via the Back Office Configuration screens.

1. Create a custom notification

Go to Configuration > Outbound Messages > Notifications, and add a custom notification. Base yourself on the following code example and tailor it to your need by modifing the id and the topic id. Leave the rest unchanged.

Code Block
"email_sent_to_client":{ //notification id, we will reference it in the workflow
  "media":{
    "webhook_topic":[
      "email_sent_to_client_topic" //topic id, we will then create it through API
    ]
  },
  "time_type": "duration",
  "time_value": "0s"
}

...

2. Create the custom topic

In order to configure a webhook via API the topic must be set using the route POST /webhook_topics as shown below.

POST /webhook_topics

Code Block
languagejson
{
    "site_id": "My_Site_ID",
    "token":"token",
    "webhook_topic":[ {
        "topic": "email_sent_to_client_topic", //custom topic id,
we will the create it through API  "ordered": true //messages ]order will  },
  "time_type": "duration",be respected
   "time_value": "0s" }
}

...

3. Subcribe a webhook to the custom topic

In order to configure a webhook via API the topic must be set We must add a listener to the custom topic. To do so, we just need to create a webhook using the route POST /webhook_topics as shown below.webhooks

POST /webhook_topicswebhooks

language
Code Block
json
{
 
  "site_id": "My_Site_IDMySiteID",
 
  "token":"token",
 
  "webhook_topic": {
        "topic": "hash_key": "personnal_hash_key",
    "http_method": "POST",
    "status": "enabled",
    "topics": [
      "email_sent_to_client_topic", //custom topic
id    ],
    "orderedurl": true"https://myWebhookURL" //messagesyou can ordergenerate willa bedisposbel respectedone at https://webhook.site/
  }
}

...

4. Trigger the custom

...

We must add a listener to the custom topic. To do so, we just need to create a webhook using the route POST /webhooks

POST /webhooks

...

notification from the workflow

Add a send notification event in the transition that must trigger the custom notification, an set the custom name, in our case, email_sent_to_client

...

Video walkthrough

...

5. Test that all works correctly

Note

Upon receiving a message via webhook, it is essential to return a 202 Accepted response promptly (within 15 seconds, but ideally under 300 ms) after verifying the message’s legitimacy (optional but recommended)

To do so, you can simply create a disposabel webhook endpoint going to https://webhook.site/ and use it as the url of your topic (by clicking on edit you can change the response code do 202, only 100 webhook receptions are allowed for free). In the case of our example, when a parcel transitions from newbagged , as when bagged in the Store App, we should receive a body as the following

Code Block
languagejson
{
  "object_id": "66fd0deab4fefe10957e49fe",
  "webhookobject_type": {
 "parcel",
  "hashorder_keyid": "personnalDV00000007_hash_keyMC",
 
  "http_methodparams": "POST",{
    "statusinformation": "enabled",triggered     "topics": [
      "email_sent_to_client_topic"
    ],
    "url": "https://myWebhookURL" //you can generate a disposbel one at https://webhook.site/from workflow"
  }
}

...

4.

...

Add a send notification event in the transition that must trigger the custom notification, an set the custom name, in our case, email_sent_to_client

...

Video walkthrough

...

5. Test that all works correctly

...

Acknowledgment of Webhook Receipt

Note

Upon receiving a message via webhook, it is essential to return a 202 Accepted response promptly (within 15 seconds, but ideally under 300 ms) after verifying the message’s legitimacy (optional but recommended)

Upon receiving a message via webhook, it is essential to return a 202 Accepted response promptly (within 15 seconds, but ideally under 300 ms) after verifying the message’s legitimacy (optional but recommended)

...

To do so, you can simply create a disposabel webhook endpoint going to https://webhook.site/ and use it as the url of your topic (by clicking on edit you can change the response code do 202, only 100 webhook receptions are allowed for free). In the case of our example, when a parcel transitions from newbagged , as when bagged in the Store App, we should receive a body as the following

Code Block
{
  "object_id": "66fd0deab4fefe10957e49fe",
  "object_type": "parcel",
  "order_id": "DV00000007_MC",
  "params": {
    "information": "triggered from workflow"
  }
}

...

4. Acknowledgment of Webhook Receipt

Note

Upon receiving a message via webhook, it is essential to return a 202 Accepted response promptly (within 15 seconds, but ideally under 300 ms) after verifying the message’s legitimacy (optional but recommended)

Upon receiving a message via webhook, it is essential to return a 202 Accepted response promptly (within 15 seconds, but ideally under 300 ms) after verifying the message’s legitimacy (optional but recommended). If this acknowledgment is not received in time, the system will retry sending the message according to the retry_intervals configuration, if retries are not acknowledged under 15 seconds.

To maintain synchronization between OneStock and your service, please acknowledge incoming webhook messages immediately. Delays can cause desynchronization and data inconsistencies. We recommend processing messages asynchronously and sending acknowledgments promptly to ensure smooth integration.

Legitimacy Check

While optional, OneStock strongly recommends performing a legitimacy check to ensure that the webhook message is genuinely sent by the OneStock system.

Each webhook message includes a signature in the header with the following format: timestamp + "." + signature.

During webhook setup (POST /webhooks), a hash key is either provided by the client or generated by OneStock. This key, referred to as h0, is used to encrypt the signature. OneStock retains the three most recent hash keys (h0, h1, h2) to support ongoing signature verification.

The signature format is:
t=timestamp.h0=h[0],h1=h[1],h2=h[2], where:

  • timestamp: The current timestamp.

  • h[0]: The signature encrypted using the latest hash key.

  • h[1]: The signature encrypted using the previous hash key.

  • h[2]: The signature encrypted using the oldest hash key.

...

. If this acknowledgment is not received in time, the system will retry sending the message according to the retry_intervals configuration, if retries are not acknowledged under 15 seconds.

To maintain synchronization between OneStock and your service, please acknowledge incoming webhook messages immediately. Delays can cause desynchronization and data inconsistencies. We recommend processing messages asynchronously and sending acknowledgments promptly to ensure smooth integration.

Legitimacy Check

While optional, OneStock strongly recommends performing a legitimacy check to ensure that the webhook message is genuinely sent by the OneStock system.

Each webhook message includes a signature in the header with the following format: timestamp + "." + signature.

During webhook setup (POST /webhooks), a hash key is either provided by the client or generated by OneStock. This key, referred to as h0, is used to encrypt the signature. OneStock retains the three most recent hash keys (h0, h1, h2) to support ongoing signature verification.

The signature format is:
t=timestamp.h0=h[0],h1=h[1],h2=h[2], where:

  • timestamp: The current timestamp.

  • h[0]: The signature encrypted using the latest hash key.

  • h[1]: The signature encrypted using the previous hash key.

  • h[2]: The signature encrypted using the oldest hash key.

Examples of signature and verification code

Expand
titleExample of signature model

Current timestamp = 1704092400

Encryption of h0 for 1704092400 = 1234 (encryption of the timestamp with the new key)

Encryption of h1 for 1704092400= 9876 (encryption of the timestamp with the previous key)

The signature will be the following : t=1704092400.h0=1234.h1=9876

Resulting the header : Onestock-Signature=t=1704092400.h0=1234,h1=9876

...

  • Prevent Queue Blocking: By acknowledging based solely on signature validation, the message queue remains smooth and uninterrupted.

  • Efficient Processing: Additional content checks can be handled asynchronously, avoiding potential bottlenecks.

5. Retries

...

, Error Management and Alerts

If acknowledgment is not received within the configured time frame, the system will retry sending the message. Notifications regarding errors can be sent via SMS, email, or both.Reponse Statuses:

Events

  1. on_failure: Triggered after the maximum number of retries (retries_until_failure) is reached without acknowledgment. This indicates that the message failed to be deliveredRetries count do not include the original message (the first one which was not ackowledged).

  2. on_failure_recovered: Triggered when a failed message is later acknowledged during a retry. The retry count resets to 0.

  3. on_deactivation: Triggered when the maximum retry attempts are exhausted without recovery. The webhook is automatically disabled and must be manually reactivated.

To resolve these errors, ensure your web service is functional and restart the webhook by setting it’s status to enabled with a PATCH /webhooks/:id/status.

Code Block
PATCH /webhooks/:id/status 
{ "site_id": "{{site_id}}", "token": "{{token}}", "status": "enabled" }

6. Webhook Statuses

  • enabled: The default state after creation. Messages are processed normally, triggering the webhook.

  • Paused: Messages are stored while the webhook is in a paused state. The behavior of this state depends on the scenario:

    • Manual pause: No messages will be sent until the webhook is manually re-enabled.

    • Automatic pause: This occurs when a message is not acknowledged by the receiver within 15 seconds. In this case, the message will be retried. If the message fails to be acknowledged after the configured number of retries (retries_until_failure), an on_failure notification will be triggered (via email and/or SMS, depending on configuration). If the maximum number of retries is reached without success, the webhook will be disabled. However, if the message is acknowledged before reaching the retry limit, the webhook will automatically resume sending messages (enabled).

  • disabled: The webhook stops functioning and storing messages after an on_deactivation error. It must be manually reactivated.

7. Message storage

Messages are stored for a week; those older than a week are automatically deleted.

8. Integration best practices

...

Code Block
PATCH /webhooks/:id/status 
{ "site_id": "{{site_id}}", "token": "{{token}}", "status": "enabled" }

Alerts

...

Emails and SMS are sent to notify webhook events stated above.

This are configured in the site configuration

Code Block
languagejson
 "on_failure": {
    "contact_emails": [ //email alert recipients. In test environments emails are sent to test recipients set in Configuration/Outbound/Media/Test Emails
      "email@company.com"
    ],
    "contact_mobiles": [],
    "sms_notification_name": "",
    "email_notification_name": "webhook_failure" //do not change
  },
  "on_deactivation": {
    "contact_emails": [ //email alert recipients. In test environments emails are sent to test recipients set in Configuration/Outbound/Media/Test Emails
      "email@company.com"
    ],
    "contact_mobiles": [],
    "sms_notification_name": "",
    "email_notification_name": "webhook_deactivation" //do not change
  },
  "on_failure_recovered": {
    "contact_emails": [ //email alert recipients. In test environments emails are sent to test recipients set in Configuration/Outbound/Media/Test Emails
      "email@company.com"
    ],
    "contact_mobiles": [],
    "sms_notification_name": "",
    "email_notification_name": "webhook_failure_recovered" //do not change
  }

6. Webhook Statuses

  • enabled: The default state after creation. Messages are processed normally, triggering the webhook.

  • Paused: Messages are stored while the webhook is in a paused state. The behavior of this state depends on the scenario:

    • Manual pause: No messages will be sent until the webhook is manually re-enabled.

    • Automatic pause: This occurs when a message is not acknowledged by the receiver within 15 seconds. In this case, the message will be retried. If the message fails to be acknowledged after the configured number of retries (retries_until_failure), an on_failure notification will be triggered (via email and/or SMS, depending on configuration). If the maximum number of retries is reached without success, the webhook will be disabled. However, if the message is acknowledged before reaching the retry limit, the webhook will automatically resume sending messages (enabled).

  • disabled: The webhook stops functioning and storing messages after an on_deactivation error. It must be manually reactivated.

7. Message storage

Messages are stored for a week; those older than a week are automatically deleted.

8. Integration Requirements

1. Handling Idempotency in Webhook Integration

When integrating with OneStock's webhook system, it is crucial that your webhook client handles idempotency. OneStock expects all webhook clients to process messages in an idempotent manner to ensure consistency and reliability.

What Is Idempotency?

Idempotency refers to the property of certain operations where executing them multiple times yields the same result as executing them once. In the context of webhooks, this means that if the same message is received more than once, processing it multiple times does not cause unintended side effects or data inconsistencies.

Why Is Idempotency Important?

Due to network issues or other transient problems, a message sent by OneStock might not be acknowledged by your system. In such cases, OneStock will retry sending the same message to ensure it has been received and processed.

If your webhook client does not handle idempotency:

  • Duplicate processing: The same operation might be performed multiple times (e.g., applying the same order change repeatedly), leading to inconsistent data or errors.

  • Integration breakdowns: Critical systems like your ERP might encounter conflicts or errors due to repeated operations, potentially disrupting business processes.

How to Handle Idempotency

Use the message-id Header

Each webhook message sent by OneStock includes a unique message-id in the HTTP headers. This identifier is essential for ensuring idempotent processing.

Implement Message Queueing and Asynchronous Processing
  1. Acknowledge Immediately: Upon receiving a webhook message, your system should send an acknowledgement to OneStock immediately.

  2. Enqueue the Message: Store the message-id and the message payload in a reliable queue for asynchronous processing.

  3. Process Asynchronously: Use a separate worker or process to consume messages from the queue and handle the idempotency checks.

Ensure Idempotency in Asynchronous Processing
  • Store processed message IDs: Maintain a persistent record of all processed message-ids.

  • Check before processing: Before processing a message from the queue, check if its message-id exists in your records.

    • If it exists: Skip processing.

    • If it does not exist: Process the message and then store its message-id.

Ensure Atomic Operations

To prevent race conditions:

  • Atomic transactions: Combine the message processing and the storage of the message-id into a single atomic transaction.

  • Thread safety: If your application processes messages in parallel, ensure that access to the message ID store is thread-safe.

Example Implementation

Webhook Handler Function

Code Block
languagepy
function handleWebhookRequest(request):
    messageId = request.headers['message-id']
    messageBody = request.body

    // Acknowledge the message immediately
    sendAcknowledgement()

    // Enqueue the message for asynchronous processing
    enqueueMessage(messageId, messageBody)

Asynchronous Message Processor

Code Block
languagepy
function processQueuedMessage():
    while true:
        message = dequeueMessage()
        if message is not null:
            messageId = message.id
            messageBody = message.body

            if isMessageIdProcessed(messageId):
                // Skip processing as this message has already been handled
                continue

            try:
                beginTransaction()

                // Process the message
                processWebhookData(messageBody)

                // Record the message-id as processed
                storeProcessedMessageId(messageId)

                commitTransaction()
            except Exception as e:
                rollbackTransaction()
                logError(e)
                // Optionally, re-enqueue the message or handle the failure accordingly
        else:
            // No messages in the queue, wait or sleep before retrying
            wait()

Acknowledging Messages

  • Successful processing: Since you acknowledge messages immediately, ensure that your asynchronous processing handles failures internally without relying on OneStock to retry.

  • Failed processing: Implement retry mechanisms within your message processor for transient errors.

  • Network failures: Immediate acknowledgement reduces the chance of network issues causing message retries from OneStock.

Advantages of This Approach

  • Improved performance: Acknowledging immediately reduces response time and prevents timeouts.

  • Scalability: Asynchronous processing allows your system to handle a higher volume of messages efficiently.

  • Reliability: Queueing messages ensures they are not lost and can be retried in case of transient failures.

Summary

  • Handle retries gracefully: Design your webhook client to process duplicate messages without adverse effects.

  • Use message-id for idempotency: Leverage the unique message-id header provided by OneStock for tracking.

  • Process asynchronously: Acknowledge messages immediately and process them in a separate worker or process.

  • Prevent duplicate operations: Ensure that repeated messages do not cause inconsistent states or errors in your systems.

8. Integration Best practices

Use a Queuing System to Receive Messages

To ensure smooth and reliable communication, it's essential to acknowledge webhook messages swiftly—ideally within 15 seconds—by returning a 202 response code. This approach ensures that OneStock knows your system has received the message, allowing the process to continue without delays.

Why Use a Queuing System?

  • Immediate Acknowledgment: By decoupling message reception from processing, you can instantly acknowledge the receipt of the message. The queue receives and stores the message, allowing your system to process it asynchronously without holding up the response.

  • Enhanced Reliability: A queuing system provides a buffer, ensuring that even if your system is temporarily down or under heavy load, messages are not lost. They will be processed once your system is ready.

  • Easier Troubleshooting: Queuing services often come with tools that allow you to view and manage received messages, making it easier to diagnose and resolve any communication issues.

...

  • AWS SQS (Simple Queue Service)

  • Google Cloud Pub/Sub

  • Apache Kafka

...

Log Message Reception

If you choose not to use a queuing system, it's vital to implement robust logging of all received messages. Logging should include the message content and the response sent back to OneStock.

Benefits of Logging:

  • Monitoring and Auditing: Detailed logs provide a trail of received messages, which is crucial for monitoring system performance and ensuring that all messages are accounted for.

  • Incident Response: In the event of an issue, logs enable you to quickly identify and address the problem, minimizing downtime and maintaining communication integrity.

  • Compliance and Debugging: Logs can also serve as an essential resource for compliance and debugging purposes, helping you ensure that your system meets all necessary requirements and functions as expected.