At a high-level, it works like this:
Your application subscribes to callbacks.
First, subscribe to event notifications (callbacks) by creating one or more webhooks. You can create a webhook manually via the API or have your application create a webhook dynamically. Each webhook must specify:
Which Smartsheet object to monitor for events
Which events in that object should trigger a callback
The HTTPS URL (that is, "callback URL") where Smartsheet should send callbacks when any of the specified events occur within the scope of the specified Smartsheet object. (NOTE: Smartsheet webhooks do not support callbacks to servers using self-signed certificates)
Webhook examples in plain English:
"When any changes occur in Sheet_A, send a callback to https://www.example.com/abc"
"When a new row is added to Sheet_B, send a callback to https://www.example.com/def"
"When a cell value is changed in Sheet_C, send a callback to https://www.example.com/ghi"
When any of the specified events occur within an object that is being monitored by a webhook, Smartsheet sends an HTTP POST (that is, "callback") to the callback URL that is associated with the webhook.
Your application receives, acknowledges, and processes callbacks.
Your application receives the HTTP POST
, acknowledges the callback by responding with HTTP status 200, and processes the callback. Because the callbacks are "skinny", make one or more requests to the Smartsheet API to retrieve the actual data associated with the change.
Use the Smartsheet API to create and manage webhooks. See Webhooks API Reference for details about the related API operations.
Webhooks can be created and managed via Direct API Access or by a third-party app.
A webhook that is created via Direct API Access:
A webhook that is created by a third-party app:
A webhook monitors the specified scope for the specified events.
A Webhook object's scope attribute indicates the scope of the subscription. It is specified when creating a webhook, and cannot subsequently be changed.
A Webhook object's event attribute indicates the set of events that a webhook is subscribed to (that is, which events trigger a callback).
NOTE: When a row is deleted on a sheet, even if you are using a subscope to monitor columns only and the cell in that column for that row is empty, you will receive a "row.deleted" event.
Consider a Webhook object with the following attribute values:
This webhook monitors the specified sheet (id: 12345678901234) for all types of events. For example, if a row is added to the sheet, cell values are updated in the sheet, a column is deleted from the sheet, etc., a callback is sent to the webhook's callbackUrl.
An API client can create a webhook by using the Create Webhook operation. A newly created webhook is disabled by default. After successfully creating a webhook, the API client must subsequently initiate and complete the verification process before the webhook is enabled. The following diagram illustrates the process of creating and enabling a webhook.
The process occurs synchronously:
API client submits a Create Webhook request.
Smartsheet creates the webhook, but does not initially enable the webhook (enabled: false and status: "NEW_NOT_VERIFIED").
To initiate the verification process, the API client submits an Update Webhook request to specify enabled: true. (NOTE: The API client does not receive a response to this request until the verification process (steps 4 and 5) has completed.)
When Smartsheet receives the request to enable the webhook, it sends a verification request to the subscriber (that is, to the callbackUrl that the API client specified in the Create Webhook request). The request specifies a unique random value in the Smartsheet-Hook-Challenge header and contains only challenge and webhookId in the request body. The challenge value is a repeat of the header value for API clients that don't interpret header values.
The subscriber responds to the verification request by echoing back the same unique random value in the Smartsheet-Hook-Response header of the response. For API clients that don't interpret header values, you can also send a JSON body with a smartsheetHookResponse attribute and the same value that would have been in the header.
Once the subscriber has successfully acknowledged the verification request, Smartsheet enables the webhook and responds to the API client's Update Webhook request to confirm that the webhook has been enabled (enabled: true and status: "ENABLED").
When an API client attempts to enable a webhook, Smartsheet sends a verification request to the webhook's callbackUrl to verify that the subscriber expects and is able to successfully receive callbacks. The request specifies a unique random value in the Smartsheet-Hook-Challenge header and contains a JSON object in the request body with only challenge and webhookId attributes in the request body. The challenge attribute is a repeat of the header value for API clients that don't interpret header values.
To verify the webhook, the subscriber's response to the verification request must return a 200 HTTP status code and must echo back the same unique random value in the Smartsheet-Hook-Response header of the response or with a JSON smartsheetHookResponse attribute. Once Smartsheet receives this verification response, the webhook is enabled (enabled: true and status: "ENABLED").
If the subscriber does not successfully respond to the verification request, the webhook remains disabled (enabled: false and status: "DISABLED_VERIFICATION_FAILED").
When a webhook is initially created through the API, the response contains the webhook's Id. If you wish to guarantee that your server only receives callbacks for webhooks that you created, you can check the verification request's webhookId attribute against your list of created webhook Ids. If the Id is not in the list, return a response with a non-200 status code (for example, 403 Forbidden), and the webhook that initiated the verification request is disabled as described above.
NOTE: IMPORTANT: ONGOING VERIFICATION. Once a webhook has been enabled, Smartsheet sends a verification request to the webhook's callbackUrl once every 100 callbacks. The subscriber should respond to the verification request as described above -- failure to do so results in the webhook being disabled (enabled: false and status: "DISABLED_VERIFICATION_FAILED").
Duplicate webhooks are defined as two or more webhooks that meet the following conditions:
Because duplicate webhooks are functionally identical, this would ordinarily result in the callback URL being called simultaneously once for each duplicate webhook in the sheet when the sheet changes. Many duplicates can lead to too much traffic which can cause a denial of service (DOS) on the callback server.
There are no known valid use cases for duplicate webhooks; they are usually created unintentionally by API clients due to faulty or missing logic.
For this reason, as of January 2023, Smartsheet will now deduplicate webhook callbacks. This means for every set of duplicate webhooks on a sheet, Smartsheet will no longer issue one callback per webhook, and will instead only issue one total callback, for only the oldest enabled webhook.
Recommendation: When creating a webhook, first check to make sure that the sheet doesn't already contain an identical webhook. If it does, and it's disabled, re-enable it. If it's already enabled, do nothing.
A Webhook object's enabled attribute indicates whether a webhook is enabled or disabled, while the status attribute describes the reason that the webhook is enabled or disabled.
The following table lists all possible combinations of enabled and status attribute values.
Webhook.enabled | Webhook.status | Meaning | Notes |
---|---|---|---|
false | DISABLED_ADMINISTRATIVE | Webhook has been disabled by Smartsheet support. | A webhook in this state can only be re-enabled by Smartsheet (contact api@smartsheet.com). Attempting to re-enable a webhook in this state results in error code 1154. |
false | DISABLED_APP_REVOKED | Webhook has been disabled because the third-party app associated with the webhook has had its access revoked. | This is a terminal state (that is, webhook in this state cannot be re-enabled, and attempts to do so result in error code 1153). If the third-party app's access is subsequently restored, it must create new webhooks. |
false | DISABLED_BY_OWNER | Webhook has been disabled by the owner. | Owner can re-enable the webhook by using the Update Webhook operation to set enabled to true. Once the subscriber successfully acknowledges the verification request, the webhook is enabled. |
false | DISABLED_CALLBACK_FAILED | Webhook has been disabled because callback was not successfully delivered to the callback URL. | Owner can re-enable the webhook by using the Update Webhook operation to set enabled to true. Once the subscriber successfully acknowledges the verification request, the webhook is enabled. |
false | DISABLED_SCOPE_INACCESSIBLE | Webhook has been disabled because its owner lost access to the corresponding data in Smartsheet (either because the object was deleted or sharing permissions were revoked). | Webhook is automatically re-enabled if access to data is restored (for example, if deleted object is restored or sharing permissions are restored). |
false | DISABLED_VERIFICATION_FAILED | Webhook verification has failed. | Owner can re-enable the webhook by using the Update Webhook operation to set enabled to true. Once the subscriber successfully acknowledges the verification request, the webhook is enabled. |
true | ENABLED | Webhook is active. | |
false | NEW_NOT_VERIFIED | Webhook has been created but is not enabled because it has not yet been verified. | Owner can re-enable the webhook by using the Update Webhook operation to set enabled to true. Once the subscriber successfully acknowledges the verification request, the webhook is enabled. |
NOTES:
A callback is the notification that Smartsheet sends to a webhook's callbackUrl. There are two types of callbacks:
Event callback: Alerts the subscriber when the specified events have occurred in Smartsheet. This is the most common type of callback.
Status Change callback: Alerts the subscriber that a webhook has been automatically disabled due to loss of access or automatically re-enabled due to restoration of access.
A Subscriber has the ability to verify the integrity of a callback payload (that is, ensure that the message was not tampered with en route) and authenticate the identity of its sender (that is, ensure that the callback did indeed originate from Smartsheet). For more information, see Authenticating Callbacks.
NOTES:
Smartsheet sends an event callback to notify the subscriber when the specified events occur in Smartsheet.
WARNING: Any events that occur while a webhook is disabled are not communicated via callback if/when webhook is enabled.
The subscriber must respond to an event callback with a 200 HTTP status code to acknowledge that the callback was received.
If the subscriber fails to respond with a 200 status, depending on the response, Smartsheet may retry delivery up to 14 times. (The first 7 retry attempts occur with a frequency that's determined using exponential backoff; thereafter, retry attempts occur once every three hours until all retries have been exhausted.)
Subscriber response | Is retried? |
---|---|
HTTP 201 through 299 | No |
HTTP 309 through 399 | No |
HTTP 400 through 499 (except 410) | Yes |
HTTP 410 | No |
HTTP 500 through 599 | Yes |
Any other HTTP status | No |
Request timeout | Yes |
If the response is not retriable or retry attempts have been exhausted, the webhook is disabled (enabled: false and status: "DISABLED_CALLBACK_FAILED"). A webhook in this state can be re-enabled if the subscriber completes the verification process. (See Webhook Status for details.)
If a webhook's owner loses access to the object that a webhook is monitoring (either because the object was deleted or the webhook owner's access to the object was revoked in Smartsheet), Smartsheet automatically disables the webhook and sends a status change callback to alert the subscriber of this change in status. The newWebhookStatus attribute indicates that the webhook is now disabled (because the scope is inaccessible).
If the webhook owner's access to the object is subsequently restored, Smartsheet automatically re-enables the webhook and sends a status change callback to alert the subscriber of this change in status. The newWebhookStatus attribute indicates that the webhook is now enabled.
A subscriber has the ability to verify the integrity of a callback payload (that is, ensure that the message was not tampered with en route) and authenticate the identity of its sender (that is, ensure that the callback did indeed originate from Smartsheet).
When you create a new webhook, it is assigned a randomly generated sharedSecret value. The shared secret is used by Smartsheet to sign callback payloads, and should not be shared with any third parties.
To authenticate a callback request:
Calculate the HMAC of the webhook's sharedSecret and the request body. This must be done using the SHA-256 cryptographic hash algorithm.
Format the calculated value as a string in base 16.
Compare your result with the value of the Smartsheet-Hmac-SHA256 header of the request.
If the values match, you can be sure the request originated from Smartsheet and that the data has not been tampered with.
NOTE: For maximum security, you may also choose to reset your webhook's shared secret at periodic intervals.
It's possible that an application which subscribes to callbacks (using webhooks) might react to those callbacks by using the API to make additional changes in Smartsheet. But, consider the following scenario:
App1 creates a webhook to monitor Sheet-A for changes, specifying an App-1 URL as the callbackUrl for the webhook.
App-1 updates Sheet-A using the API.
Smartsheet detects that Sheet-A has changed and sends a callback to App-1 (as the webhook specified).
App-1 processes the callback, and in the course of doing so, updates Sheet-A again using the API.
Return to Step 3.
To protect against infinite loops like the one outlined above, Smartsheet introduced support for a new header that an API client can include with any API request that adds, updates, or deletes data in Smartsheet. Here's how it works:
The following table specifies the recommended action for each Smartsheet-specific error code. Use this information to implement error handling logic according to the following guidelines:
HTTP status code | Smartsheet errorCode | Smartsheet message | Recommended Action |
---|---|---|---|
400 | 1151 | Scope '{0}', object id {1} was not found. | Do not retry without fixing the problem. |
400 | 1152 | Only URLs with a protocol of 'https' are supported for attribute '{0}'. | Do not retry without fixing the problem. |
403 | 1153 | This webhook cannot be enabled because access was revoked for the application that created it. | Do not retry. |
403 | 1154 | Please contact api@smartsheet.com in order to enable this webhook. | Do not retry. |