How to Work With Webhooks
API2Cart webhook is a mechanism for getting notifications when some changes or events on shopping carts occur. For example, the order.update webhook triggers every time when the order status changes. In this case, the JSON formatted data is being sent to the specified URL.
Information on how to create a webhook
To create webhook:
-
First check which webhooks are supported for the given store. To do this, call webhook.events method. You will get the list of webhooks that are supported for the given shopping cart. Here you can get the values for the action and entity parameters, which are required for webhook.create.
-
Then create the webhook by calling webhook.create and specify the following parameters:
- entity - specify the entity that you want to enable webhook for (e.g product, order, customer, category).
- entity - specify what action (event) will trigger the webhook (e.g add, delete, or update).
- callback - specify URL to which webhook will be sent.
- fields - specifies the fields that will be included in the webhook object that will be sent to the callback. They will be similar to those for {entity}.info methods. For example, if you specify entity=product, you need to look at the list of fields for the product.info method. Default force_all.
See more details about the parameters on our documentation.
Here is the example of the request for creating a webhook:
curl --location 'https://api.api2cart.local.com/v1.1/webhook.create.json' \ --header 'x-api-key:' \ --header 'x-store-key: ' \ --header 'Content-Type: application/json' \ --data '{ "entity": "product", "action": "add", "callback": "https://example.com", "label": "Test product.add", "fields": "id,name", }'
Note: In case you are using multi store instance you can set store_id parameter to specify on which store you want create the webhook.
If the request is performed successfully and you will received the id of the webhook that you’ve just created. From now on, when new product appears on the store, you will receive webhook events on the URL, which you’ve specified in callback parameter.
If you need to distinguish webhooks coming from different connected stores, we recommend embedding a unique identifier into the callback_url when creating the webhook. For example:
https://example.com/webhook/store123/https://example.com/webhook?store=store123
This way, you can easily identify which connected store the webhook refers to on your end.
Information about the events that are sent to the callback
The events that will be sent to the callback URL contain additional header with the event info:
-
X-Webhook-Store-Id – X-Webhook-Store-Id – the internal store ID from the shopping cart platform on which the event occurred.
⚠️ Note: This is not the same as the account store ID (the ID of your connected store shown in your API2Cart account). It reflects the store ID inside the platform (for multi-store platforms like Magento). - X-Webhook-Lang-Id – language ID used to deliver the webhook content. If the store supports multiple languages and you specified lang_id when creating the webhook, this header will also be present and contain the ID of the language in which the content was provided.
- X-Webhook-Action – the event that occured (add, update, delete).
- X-Webhook-Entity – the entity that the event occurred with (product, order, etc.).
- X-Webhook-Error-Code – error code. If successful, the code equals 0.
- X-Webhook-Signature – a signature that is used to check if the request is sent by API2Cart and not a third-party pretending to be API2Cart.
- X-Webhook-Timestamp – a timestamp indicating when the webhook was triggered.
The body contains json string with new data about the entity.
Here is an example of a response:
x-webhook-action:add
x-webhook-entity:product
x-webhook-error-code:0
x-webhook-signature:93PHz0els3123j3puyrVpB/YIeBDB+xBWgvEd3YbJQ=
x-webhook-store-id:2
x-webhook-timestamp:1744109557
{"id":"86","name":"test product"}
The event is considered to be successfully delivered when the callback returns status code 200. In case the status code is anything but 200, the system sends the event one more time. If this time the status code is also not 200, then it is considered to be undelivered and it will appear in the failed events log. You can check the list of failed events using account.failed_webhooks method.
Note: We store failed webhooks data for 24 hours.
Information on how to authenticate a webhook request
API2Cart signs webhook events so you can validate that requests are sent by API2Cart and not a third-party pretending to be API2Cart.
API2Cart includes an X-Webhook-Signature header generated using the app's shared secret, along with the data sent in the request in each Webhook event.
To verify that the request came from API2Cart, compute the HMAC digest according to the following algorithm and compare it to the value in the X-Webhook-Signature header.
What you need to generate a signature:
- Headers of the request
- Request body
- Store Key
Generating Signature:
- Gather all headers starting with “X-Webhook-”.
- Remove “X-Webhook-Signature” from the array.
- Sort the headers alphabetically by the key.
- Encode the headers into JSON.
- Concatenate the strings, JSON headers string should come first.
- Hash the resulting string with HMAC SHA256 function with outputs raw binary data set true (raw_output = true). Use your store_key as a secret key to generate a binary signature.
- Encode the string in Base64.
Example of PHP implementation:
Please pay extra attention to the case of the headers so that your signature matches. Headers should be in the same case as in our example.
Additional information
What else you can do with the webhooks.
Using webhook.list method you can get the list of webhooks that were created in the store via API2Cart API.
The created webhook contain the following fields:
- id – the webhook id.
- label – the webhook name.
- store_id – store id the webhook is created on. For non-multistore instances the returned value will always be “1”.
- lang_id – The language identifier (lang_id field) is provided for webhooks that can deliver content in multiple languages. If the event or the shopping cart platform does not support multilingual separation, the field value will be NULL.
- active – webhook status.
- callback – callback URL that the webhook will send the POST request to when the event occurs.
- fields – fields that the webhook will send.
- created_at– webhook creation date.
- updated_at – last webhook update date.
- entity – the entity that the webhook is created for.
- action – the action that triggers the webhook.
You can filter the webhooks according to different fields. There are the the following parameters for this:
- entity
- action
- active
- ids
For details see the documentation.
You can also check the number of created webhooks on the store using webhook.count method.
You can change some webhook parameters using webhook.update method. To do this, you need to fill its id.
You can change only the following parameters:
- callback
- label
- fields
- active
To delete the webhook use webhook.delete method and fill in the webhook id.
Webhooks via Polling Mechanism
Most shopping carts support native webhooks. However, for platforms that do not have native webhooks functionality, API2Cart implements this feature via periodic polling. In this case, the store is polled periodically to check if any entities have been created or updated.
Polling Interval Strategy:
By default, the polling interval is 300 seconds (5 minutes). However, if the store is unavailable
or returns an error during the polling process, the interval increases automatically to reduce the load.
The interval is calculated using the formula: current interval * number of failed attempts.
After the 6th unsuccessful attempt, the webhook is automatically disabled.
The intervals based on the number of failed attempts are as follows:
- 1st failure: 300 seconds
- 2nd failure: 600 seconds
- 3rd failure: 1800 seconds
- 4th failure: 7200 seconds
- 5th failure: 36000 seconds
- 6th failure: Webhook is disabled
If a subsequent polling attempt is successful, the interval resets to the default value of 300 seconds.
Polling Error Notifications
If polling issues occur, a notification containing error details is sent to the webhook callback URL. These notifications include specific headers:
- X-Webhook-Error-Attempts-Remaining – indicates how many attempts remain before the webhook is disabled.
- X-Webhook-Error-Reason – contains details about the error reason.
- X-Webhook-Error-Code – the numeric error code.
-
X-Webhook-Error-Message – the text of the error.
If there are fewer than 6 failed attempts:
Your webhook [id: Number] has failed. If it continues to fail, the webhook will be automatically disabled. See the details in response headers.If this is the 6th failed attempt (disabling):
Your webhook [id: Number] has been disabled. Check the response headers for details and re-enable it via webhook.update once the issue is resolved.
Monitoring Polling Status
You can check if a webhook works via polling and monitor its status using the
webhook.list method.
The response will contain an additional_fields object with a polling section:
"additional_fields": {
"polling": {
"failed_attempts_count": Number, // Number of consecutive failed attempts
"last_failed_at": Null | DateTime, // Date of the last failure (or null)
"interval": Number // Current polling interval in seconds
}
}
Webhook Delivery and Error Handling
The event is considered successfully delivered when your callback URL returns a 200 OK status code.
Delivery Retry Policy:
If the callback returns any status code other than 200, API2Cart will attempt to redeliver the webhook. The system makes 10 attempts to deliver the event.
If the callback fails to return a success status after 10 attempts:
- An email notification is sent to the address registered with your API2Cart account, stating that the callback is not working.
- The webhook enters a 24-hour grace period. You must fix the callback issue within this timeframe.
- If the callback does not respond successfully within 24 hours, the webhook will be deleted.
You can monitor delivery failures using the
webhook.list method.
Look for the delivery object inside additional_fields:
"additional_fields": {
"delivery": {
"failed_attempts_count": Number, // Number of consecutive failed delivery attempts
"last_failed_at": Null | DateTime // Date of the last failed attempt
}
}
You can also check the list of specific failed events using the account.failed_webhooks method.