Create an event-handling endpoint
Your event-handling endpoints (callback endpoints) are where you receive notifications for Smartsheet events you've subscribed to via webhooks. In these endpoints, you process incoming events and act on them to fit your business processes. Additionally, your endpoints acknowledge Smartsheet's ongoing verification challenges -- pings that make sure you're still listening to your subscriptions.
This tutorial shows how to create such a webhook event-handling endpoint.
Note: The tutorial demonstrates handling sheet events, but the same principles apply to handling events for other Smartsheet objects supported by webhooks.
Note: The example endpoint is written in Python and hosted on Flask, but you can write your endpoint in whatever language you like and host it on any web framework that supports hosting REST endpoints.
Prerequisites
Smartsheet API access token. You can generate an access token (key) in the Smartsheet UI.
A web framework that supports hosting REST endpoints.
Endpoint host server with a valid SSL certificate.
Important: Smartsheet webhooks don't support self-signed certificates.
It's time to get started.
Step 1: Set up your endpoint
On your web framework, create an HTTPS endpoint that receives HTTPS POST requests.
Example Flask application:
# app.py
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/my-sheet-webhook', methods=['POST'])
def handle_callback():
# We'll update this section in the next steps
return jsonify({"message": "Callback received"}), 200
if __name__ == '__main__':
# You must use a production server like Gunicorn or Nginx
# to handle HTTPS. For development, you can use a tool like ngrok
# to expose your localhost to the internet via an HTTPS URL.
app.run(port=8000, debug=True)
The code above creates a web application with a single endpoint called /my-sheet-webhook
.
For now, it's a simple endpoint that accepts HTTP POST requests, responds with a 200
status code, and returns a JSON-formatted message stating "Callback received"
.
Note: The example's endpoint-handling function is arbitrarily called
handle_callback
, but you can name your functions whatever you like.
In this example, the server hosts the endpoint at port 8000
.
Important: Here are the valid ports for hosting Smartsheet webhook event-handling endpoints:
443
(default for HTTPS),8000
,8008
,8080
, or8443
.
You've laid the foundation for your endpoint. Next, add logic for acknowledging Smartsheet verification challenges.
Step 2: Handle verification challenges
When you activate a new webhook in Smartsheet, Smartsheet sends a verification challenge to its endpoint to make sure the endpoint is valid. Your endpoint must respond to this challenge correctly to qualify for receiving webhook events.
The challenge request contains a unique, randomly-generated challenge value -- the request contains the value in two locations:
Smartsheet-Hook-Challenge
headerRequest body
challenge
field
To pass the challenge, you must implement your endpoint to include these things in response to verification challenges:
HTTP status code of
200
The challenge value. You must include the value in either of these locations:
- Response header named
Smartsheet-Hook-Response
- JSON-formatted response body attribute called
smartsheetHookResponse
- Response header named
Update your endpoint code to satisfy the above-mentioned challenge requirements.
For example,
@app.route('/my-sheet-webhook', methods=['POST'])
def handle_callback():
# Check for the Smartsheet verification challenge
challenge_value = request.headers.get('Smartsheet-Hook-Challenge')
if challenge_value:
print(f"Received verification challenge: {challenge_value}")
# Respond with the challenge value in the required header
response = jsonify({"message": "Challenge accepted"})
response.headers['Smartsheet-Hook-Response'] = challenge_value
return response, 200
# If it's not a challenge, proceed to handle the event callback
return process_sheet_event(request.json)
def process_sheet_event(data):
# This is a placeholder function for the next step
print("Received event callback payload.")
# Log the received data for now
print(data)
return jsonify({"message": "Event processed successfully"}), 200
The handle_callback
function above first checks for the presence of the Smartsheet-Hook-Challenge
header. If the header exists, we extract its value, print a message (optional), and return a 200
OK response that includes the Smartsheet-Hook-Response
header set to the challenge value from the request.
The endpoint now handles Smartsheet verification challenges. Handling events is next!
Not: The webhook callback processing function above is arbitrarily named
process_sheet_event
-- you can name your functions whatever you like.
Step 3: Process callback events
Eventually, when you launch your webhook (covered in the next article), it sends callbacks to your endpoint.
Each callback is a JSON-formatted HTTP POST request that contains information about events that have occurred that match your webhook's event subscription. For example, a sheet webhook callback may include events such as these:
- A row was added
- A cell was updated
- and more ...
The callback's JSON-formatted body has an events
array that details the changes.
Note: See the Callback schema and specifically its
events
attribute, to learn more about callback events.
Update your endpoint to process the events to which you're subscribing.
The updated script below iterates over the sheet events and has a placeholder for event-handling logic.
from flask import Flask, request, jsonify
import json
app = Flask(__name__)
def process_webhook_callback(event_data):
"""
Processes a Smartsheet sheet event.
"""
print("Processing sheet event...")
# Example: Print the sheet ID and the event type
sheet_id = event_data.get('objectInfo', {}).get('id')
event_type = event_data.get('eventType')
if sheet_id and event_type:
print(f"Sheet ID: {sheet_id}, Event Type: {event_type}")
# Here you would add your custom business logic.
# For example, updating a database, sending an email, or triggering a workflow.
print("-" * 20)
@app.route('/my-sheet-webhook', methods=['POST'])
def handle_callback():
# Handle the Smartsheet verification challenge
challenge_value = request.headers.get('Smartsheet-Hook-Challenge')
if challenge_value:
print("Received verification challenge...")
response = jsonify({"message": "Challenge accepted"})
response.headers['Smartsheet-Hook-Response'] = challenge_value
return response, 200
# Handle the event callback
try:
payload = request.json
print("Received event callback payload.")
# A webhook can contain multiple events in the 'events' array
events = payload.get('events', [])
for event in events:
# We are interested in events related to sheets
if event.get('objectType') == 'sheet':
process_sheet_event(event)
return jsonify({"message": "Event processed successfully"}), 200
except json.JSONDecodeError:
print("Invalid JSON received.")
return jsonify({"message": "Invalid JSON"}), 400
except Exception as e:
print(f"An error occurred: {e}")
return jsonify({"message": "Internal server error"}), 500
if __name__ == '__main__':
app.run(port=8000, debug=True)
The above application's handle_callback
function handles verification challenges and callback events. It passes each callback event to a function called process_sheet_event
.
This example's process_sheet_event
function is a placeholder for processing events. You can add event-processing logic here to examine the events and act on them to fit your business needs.
You've created an endpoint that handles Smartsheet verification challenges and is ready for your custom event processing business logic!
Add your custom event-processing logic. Then launch your webhook!