Skip to main content

Webhook

A Webhook is a tool that allows you to receive a notification for a certain event. It allows you to register an https URL which will receive the event data, stored in JSON. Webhooks can be registered for the following events:

CategoryEvents
Appuninstalled/suspended/resumed
Categorycreated/updated/deleted
Ordercreated/updated/paid/packed/fulfilled/cancelled/custom_fields_updated/edited/pending/voided
Productcreated/updated/deleted
Product Variantcustom_fields_updated
Domainupdated
Order Custom Fieldcreated/updated/deleted
Product Variant Custom Fieldcreated/updated/deleted

To register for the product created event, for example, you should send product/created in the event field. Basically, you make a POST request in Webhooks endpoint providing a body with the type of webhook you want to create as well as the URL where you will be notified.

Now let's say you want to be notified whenever an order gets paid so you don't have to make scheduled calls to retrieve this information. Here you should create a Webhook with the event order/paid and the URL where you will be notified in your backend.

The app/suspended and app/resumed events refer to the suspension of API access due to lack of payment.

You are not allowed to use a localhost/tiendanube/nuvemshop domain for webhooks.

To aid in your development you can use RequestCatcher. PostCatcher is a web app that generates a unique url that you can use as a webhook endpoint and display any POST requests sent to it for you to examine.

About the Ordering and Idempotency of Messages

It's worth noticing that webhook messages are managed through a distributed system, so they are handled by multiple separate servers working in parallel to ensure quick, reliable, and efficient processing of the thousands of messages we send per minute. Because of the nature of the distributed system, we cannot ensure that the order they are being queued to be processed is the same as the order they are being processed.

Additionally, some messages may be sent multiple times with the same content. Those messages should be treated as unique. It is the responsibility of the developer integrating their service with our webhook to ensure idempotency.

Rules for Deduplication

  • Messages sent with identical message bodies must be treated as unique.
  • Messages sent with identical content but different message attributes must be treated as unique.
  • Messages sent with different content (for example, retry counts included in the message body) must be treated as duplicates.

Properties

PropertyExplanation
idThe unique numeric identifier for the Webhook
urlThe URL where the webhook should send the POST request when the event occurs. Must be HTTPS.
eventThe event that will trigger the webhook
created_atDate when the Webhook was created in ISO 8601 format
updated_atDate when the Webhook was last updated in ISO 8601 format

Verifying a webhook

Webhooks created through the API can be verified by calculating a digital signature.

Each Webhook request includes a x-linkedstore-hmac-sha256 header which is generated using the app's secret, along with the data sent in the request.

Note that some frameworks will change the header to HTTP_X_LINKEDSTORE_HMAC_SHA256.

See PHP example below:

<?php

define('APP_SECRET', 'secret');

function verify_webhook($data, $hmac_header) {
return $hmac_header == hash_hmac('sha256', $data, APP_SECRET);
}

$hmac_header = $_SERVER['HTTP_X_LINKEDSTORE_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
echo 'Webhook verified: ' . var_export($verified, true);

Parameters

When doing the POST request, all webhooks will send the following parameters in JSON format:

  • store_id: Store from where the event originated (received as user_id at the authentication step
  • event: Event's name (product/created, product/updated, etc.)

Also, every webhook will send custom parameters, as follows:

app/uninstalled

  • id: App's id.

category/created - category/updated - category/deleted

  • id: Category's id.

order/created - order/updated - order/paid - order/packed - order/fulfilled - order/cancelled - order/custom_fields_updated - order/edited - order/pending - order/voided

  • id: Order's id.

product/created - product/updated - product/deleted

  • id: Product's id.

product_variant/custom_fields_updated

  • id: Product's Variant id.

domain/updated

No additional parameter is sent along with this event. To get the list of domains one may refer to Store resources.

order_custom_field/created - order_custom_field/updated - order_custom_field/deleted

  • id: CustomField's id.

product_variant_custom_field/created - product_variant_custom_field/updated - product_variant_custom_field/deleted

  • id: CustomField's id.

Example webhook content

{
'store_id':123,
'event':'product/created',
'id':1948209
}

Retry policies

A Webhook notification expects a 2XX status code in response (to guarantee that the App has received the notification) and has a timeout of 10 seconds. That is, we wait 10 seconds for a 2XX code in response (it can be any code that starts with 2 - 200/201, etc).

When a webhook notification cannot be delivered due to a problem (e.g when the App is down) then retry policy is on.

The first 4 retries are: one immediately after timeout and then at approximately 5, 10 and 15 minutes. Then it starts to do exponential backoff multiplying the waiting time of the previous one by 1.4 within the next 48 hours (up to 18 attempts).

Overview of the process:

  • We send the webhook.
  • We wait 10 seconds for response confirmation by the App.
  • If we do not receive any responses, then retry policy is activated.

A success response code will stop next notifications. But, if that does not happen at all, notifications will be sent 18 times.

Required Webhooks

In order for our company to comply with data protection laws (example LGPD in Brazil), we provide Webhooks that facilitate communication between consumers, merchants and integrated applications, to trigger notices of removal or update of shared data, when a request is received for us.

Basically, the LPGD obliges technology platforms to provide mechanisms through which data owners can:

  • Request a report from the platform to find out what personal data of that person it has.
  • Request the platform to delete personal data.

Tiendanube apps are digital platforms that can store data from both merchants and consumers. That is why partners also have the responsibility to comply with this law. They are obliged to delete data or to report what data they have, whenever requested.

So that partners can find out about these orders, from Tiendanube we created this mechanism of webhooks. Webhooks represent automatic notifications that Tiendanube will send to partners when specific events occur that require deleting/reporting data. These webhooks are three:

image

store/redact

Request to delete store information. 48 hours after a store uninstalls your app, Nuvemshop|Tiendanube sends this webhook with the store ID so that you can delete the shopkeeper's information from your database. Payload:

{
store_id: 123;
}

customers/redact

Request to erase consumer information. If the consumer did not place an order at the store 6 months ago, the webhook will be sent after 5 days. If the customer has placed an order in the last 6 months, the deleted order will be held until 6 months have passed. Payload:

{
store_id: 123,
customer: {
id: 1,
email: email@email.com
phone: +55...,
identification: ...
},
orders_to_redact: [213, 3415, 21515]
}

customers/data_request

Request for customer information. It is the application's responsibility to send the information directly to the merchant. Payload:


{
store_id: 123,
customer: {
id: 1,
email: email@email.com
phone: +55...,
identification: ...
},
orders_requested: [213, 3415, 21515],
checkouts_requested: [214, 3416, 21518],
drafts_orders_requested: [10, 1245, 5456],
data_request: {
id: 456,
}
}

Endpoints

GET /webhooks

Receive a list of all Webhooks for your application.

ParameterExplanation
since_idRestrict results to after the specified ID
urlShow webhooks tags with a given URL
eventShow webhooks with a given event
created_at_minShow Webhooks created after date (ISO 8601 format)
created_at_maxShow Webhooks created before date (ISO 8601 format)
updated_at_minShow Webhooks last updated after date (ISO 8601 format)
updated_at_maxShow Webhooks last updated before date (ISO 8601 format)
pagePage to show
per_pageAmount of results
fieldsComma-separated list of fields to include in the response

GET /webhooks

HTTP/1.1 200 OK

[
{
"created_at": "2013-01-03T09:11:51-03:00",
"event": "app/uninstalled",
"id": 101,
"updated_at": "2013-03-11T09:14:11-03:00",
"url": "https://myapp.com/uninstall"
},
{
"created_at": "2013-04-07T09:11:51-03:00",
"event": "order/created",
"id": 5670,
"updated_at": "2013-04-08T11:11:51-03:00",
"url": "https://myapp.com/order_created_hook"
}
]

GET /webhooks?since_id=1234

HTTP/1.1 200 OK

[
{
"created_at": "2013-04-07T09:11:51-03:00",
"event": "order/created",
"id": 5670,
"updated_at": "2013-04-08T11:11:51-03:00",
"url": "https://myapp.com/order_created_hook"
}
]

GET /webhooks/{id}

Receive a single Webhook

ParameterExplanation
fieldsComma-separated list of fields to include in the response

GET /webhooks/5670

HTTP/1.1 200 OK

{
"created_at": "2013-04-07T09:11:51-03:00",
"event": "order/created",
"id": 5670,
"updated_at": "2013-04-08T11:11:51-03:00",
"url": "https://myapp.com/order_created_hook"
}

POST /webhooks

Create a new Webhook

POST /webhooks

{
"url": "foobar",
"event": "invalid_event"
}

HTTP/1.1 422 Unprocessable Entity

{
"event": [
"Invalid event specified. Events allowed are available on Parameters section: https://tiendanube.github.io/api-documentation/resources/webhook#parameters"
],
"url": ["invalid url specified"]
}

POST /webhooks

{
"event": "product/created",
"url": "https://myapp.com/product_created_hook"
}

HTTP/1.1 201 Created

{
"created_at": "2013-06-01T15:12:15-03:00",
"event": "product/created",
"id": 8901,
"updated_at": "2013-06-01T15:12:15-03:00",
"url": "https://myapp.com/product_created_hook"
}

PUT /webhooks/{id}

Modify an existing Webhook

PUT /webhooks/5670

{
"created_at": "2013-04-07T09:11:51-03:00",
"event": "category/created",
"id": 5670,
"updated_at": "2013-04-08T11:11:51-03:00",
"url": "https://myapp.com/category_created_hook"
}

HTTP/1.1 200 OK

{
"created_at": "2013-04-07T09:11:51-03:00",
"event": "category/created",
"id": 5670,
"updated_at": "2013-06-01T12:11:14-03:00",
"url": "https://myapp.com/category_created_hook"
}

DELETE /webhooks/{id}

Remove a Webhook

DELETE /webhooks/5670

HTTP/1.1 200 OK

{}