See Webhooks guide page for details on how you can use webhooks to receive notifications from activities in Labelbox.
Configure server to receive requests
# This can be any secret that matches your webhook config (we will set later)
secret = b"CHANGE-ME"
# Example for server-side code to receive webhook events
app = Flask(__name__)
@app.route("/webhook-endpoint", methods=["POST"])
def print_webhook_info():
payload = request.data
computed_signature = hmac.new(secret, msg=payload,
digestmod=hashlib.sha1).hexdigest()
if request.headers["X-Hub-Signature"] != "sha1=" + computed_signature:
print(
"Error: computed_signature does not match signature provided in the headers"
)
return "Error", 500, 200
print("=========== New Webhook Delivery ============")
print("Delivery ID: %s" % request.headers["X-Labelbox-Id"])
print("Event: %s" % request.headers["X-Labelbox-Event"])
print("Payload: %s" %
json.dumps(json.loads(payload.decode("utf8")), indent=4))
return "Success"
thread = threading.Thread(target=lambda: run_simple("0.0.0.0", 3001, app))
thread.start()
Create webhook
Export v2 payload
To create a webhook with Export v2 payload, you need to set up a Export v2 webhook in Project UI first.
Export v1 payload
You can create webhook v1 webhook via UI or via the Python SDK below.
from labelbox import Client, Webhook
public_url = "https://example.com/webhook-endpoint" # Your server's public url - where the messages will be sent to
secret = b"CHANGE-ME" # Use to verify Labelbox is sending the message
client = Client(api_key="<YOUR_API_KEY>")
project = client.get_project("<project_id>")
print([topic.value for topic in Webhook.Topic]) # See all available topics
secret = b"example_secret" # This can be any secret that matches your webhook config (we will set later)
webhook = Webhook.create(client,
topics=["LABEL_CREATED"],
url="public_url",
secret=secret.decode(),
project=project)
Get webhooks
# Fetch all webhooks
org = client.get_organization()
webhooks = org.webhooks() #paginated
# Fetch project webhooks
project = client.get_project("<project_id>")
webhooks = project.webhooks() #paginated
webhook = next(webhooks)
status = webhook.status
server_url = webhook.url
topics = webhook.topics
project = webhook.project()
Update webhook
# url, topics, and status can all be updated
updated_url = f"{public_url}/webhook-endpoint"
webhook.update(url=updated_url, topics=[Topic.LABEL_DELTED], status=Webhook.Status.INACTIVE.value)
Delete webhook
webhook.delete()
Code sample
public_url = "https://example.com/webhook-endpoint" # Where the messages will be sent
secret = b"CHANGE-ME" # Use to verify Labelbox is sending the message
client = Client()
project = client.get_project("<project-id>")
# Create a project specific webhook (Export v1 only)
topics = {topic.value for topic in Webhook.Topic} # Specify 1+ topics
webhook = Webhook.create(
client,
topics=topics,
url=public_url,
secret=secret.decode(),
project=project
)
# --- Example Flask Server Code ---
@app.route("/webhook-endpoint", methods=["POST"])
def print_webhook_info():
payload = request.data
computed_signature = hmac.new(
secret,
msg=payload,
digestmod=hashlib.sha1
).hexdigest()
if request.headers["X-Hub-Signature"] != "sha1=" + computed_signature:
print(
"Error: computed_signature does not match signature provided in the headers"
)
return "Error", 500, 200
print("=========== New Webhook Delivery ============")
print("Delivery ID: %s" % request.headers["X-Labelbox-Id"])
print("Event: %s" % request.headers["X-Labelbox-Event"])
print("Payload: %s" % json.dumps(json.loads(payload.decode("utf8")), indent=4))
return "Success"
Sample response
v2
If you configure a v2 webhook, the payload will be the same as the Export v2 payload.
v1
{'agreement': None,
'benchmarkAgreement': None,
'createdAt': '2023-02-13T18:22:46Z',
'dataRow': {'createdAt': '2023-01-25T17:54:20Z',
'deletedAt': None,
'externalId': 'multi_thread_update_4cfdcb29-be33-4e07-b586-849829385210',
'id': 'cldbyu7c7n4jp072scuqt66ll',
'labelCountInProject': 1,
'rowData': 'https://labelbox.s3-us-west-2.amazonaws.com/datasets/mapillary_traffic/images/F1xqHzDSi1qP3qSLBXVyJQ.jpg',
'updatedAt': '2023-01-25T20:42:57Z'},
'dataset': {'createdAt': '2023-01-25T17:53:58Z',
'deleted': False,
'description': '',
'id': 'cldbytq0w2uw8074hgl3hbxr2',
'name': 'Datarow Update Test - 5K',
'updatedAt': '2023-01-25T17:54:21Z'},
'deleted': False,
'id': 'cle357uex0g5307z996y28ic0',
'label': '{"objects":[{"featureId":"cle357vrp00013b6jsi6dfei0","schemaId":"cldan3u0701sc07yi6xyw6up6","color":"#ff0000","title":"bounding_box","value":"bounding_box","bbox":{"top":453,"left":951,"height":670,"width":952},"instanceURI":"https://api.labelbox.com/masks/feature/cle357vrp00013b6jsi6dfei0"}],"classifications":[],"relationships":[]}',
'project': {'createdAt': '2023-02-13T18:20:52Z',
'deleted': False,
'description': '',
'id': 'cle355i370h86070hf1v7ata1',
'name': 'Webhooks',
'updatedAt': '2023-02-13T18:22:17Z'},
'secondsToLabel': 0,
'skipped': False,
'updatedAt': '2023-02-13T18:22:46Z',
'user': {'email': '[email protected]',
'id': 'clbpgxfaehww6076tedo5ejwx'}}
{
"id": "cl4g555g81ltr07cka1a2b1wv",
"createdAt": "2022-06-16T19:41:49Z",
"updatedAt": "2022-06-16T19:58:25Z",
"secondsToLabel": 6.002,
"label": "{\"objects\":[{\"featureId\":\"cl4hg2phm00013b6j2thsko0u\",\"schemaId\":\"cl2i6hbju1o2y10a321w3cusv\",\"title\":\"grape\",\"value\":\"grape\",\"color\":\"#1CE6FF\",\"bbox\":{\"top\":298,\"left\":445,\"height\":520,\"width\":930},\"instanceURI\":\"https://api.labelbox.com/masks/feature/cl4hg2phm00013b6j2thsko0u\"}],\"classifications\":[],\"relationships\":[]}",
"agreement": null,
"benchmarkAgreement": null,
"deleted": false,
"skipped": false,
"labelCountInProject": 2,
"project": {
"id": "cl2i6gssn1o2210a3gq549fq0",
"createdAt": "2022-04-27T22:57:43Z",
"updatedAt": "2022-06-15T22:19:36Z",
"name": "grapes",
"description": "",
"deleted": false
},
"dataRow": {
"id": "cl2hzfg8g18kw0ztwbtnq0b6q",
"createdAt": "2022-04-27T19:40:43Z",
"updatedAt": "2022-04-27T20:13:51Z",
"deletedAt": null,
"externalId": "CFR_1620.jpg",
"rowData": "https://storage.labelbox.com/ckhmnux5zeutm0825bt0kj34y%2F5375dc13-6442-22d7-f523-e9d252e715ea-CFR_1620.jpg?Expires=1656619105&KeyName=labelbox-assets-key-3&Signature=iOg3tbKe4j7xWZHw1r5rQD4iJIk="
},
"dataset": {
"id": "cl2hz9qay0unl10a3f4wmcsfi",
"createdAt": "2022-04-27T19:36:16Z",
"updatedAt": "2022-04-27T19:40:43Z",
"name": "data",
"description": "",
"deleted": false
},
"user": {
"id": "ckhmnux6hi0p907898jext199",
"email": "[email protected]"
}
}
{
"id": "cl2i6hegh1x660z9i9fzz01a0",
"createdAt": "2022-04-27T22:58:35Z",
"updatedAt": "2022-06-16T20:12:41Z",
"secondsToLabel": 31.448,
"label": "{\"objects\":[{\"featureId\":\"cl2i6hhgd00013f6ghfnrcn6h\",\"schemaId\":\"cl2i6hbju1o2y10a321w3cusv\",\"title\":\"grape\",\"value\":\"grape\",\"color\":\"#1CE6FF\",\"bbox\":{\"top\":701,\"left\":402,\"height\":316,\"width\":238},\"instanceURI\":\"https://api.labelbox.com/masks/feature/cl2i6hhgd00013f6ghfnrcn6h\"},{\"featureId\":\"cl2i6hp3h00033f6gaofl29lx\",\"schemaId\":\"cl2i6hbju1o3010a30ksn2yiy\",\"title\":\"grape mask\",\"value\":\"grape_mask\",\"color\":\"#FF34FF\",\"instanceURI\":\"https://api.labelbox.com/masks/feature/cl2i6hp3h00033f6gaofl29lx\"}],\"classifications\":[],\"relationships\":[]}",
"agreement": null,
"benchmarkAgreement": null,
"deleted": true,
"skipped": false,
"labelCountInProject": 1,
"project": {
"id": "cl2i6gssn1o2210a3gq549fq0",
"createdAt": "2022-04-27T22:57:43Z",
"updatedAt": "2022-06-16T20:06:25Z",
"name": "grapes",
"description": "",
"deleted": false
},
"dataRow": {
"id": "cl2hzfg8g18kk0ztwg22ke4vz",
"createdAt": "2022-04-27T19:40:43Z",
"updatedAt": "2022-04-27T20:13:52Z",
"deletedAt": null,
"externalId": "SYH_2017-04-27_1324.jpg",
"rowData": "https://storage.labelbox.com/ckhmnux5zeutm0825bt0kj34y%2F1d883928-046f-97d5-e3f7-e6c296967c7e-SYH_2017-04-27_1324.jpg?Expires=1656619961&KeyName=labelbox-assets-key-3&Signature=0ma5Yw5qxdJE6_x7ACR7aPEHePM="
},
"dataset": {
"id": "cl2hz9qay0unl10a3f4wmcsfi",
"createdAt": "2022-04-27T19:36:16Z",
"updatedAt": "2022-04-27T19:40:43Z",
"name": "data",
"description": "",
"deleted": false
},
"user": {
"id": "ckhmnux6hi0p907898jext199",
"email": "[email protected]"
}
}
{
"id": "cl4hgj3ma26wy087b1chnayro",
"createdAt": "2022-06-16T20:11:05Z",
"updatedAt": "2022-06-16T20:11:05Z",
"score": -1,
"deleted": false,
"label": {
"id": "cl4g555g81ltr07cka1a2b1wv",
"secondsToLabel": 0,
"label": "{\"objects\":[{\"featureId\":\"cl4hg2phm00013b6j2thsko0u\",\"schemaId\":\"cl2i6hbju1o2y10a321w3cusv\",\"title\":\"grape\",\"value\":\"grape\",\"color\":\"#1CE6FF\",\"bbox\":{\"top\":298,\"left\":445,\"height\":520,\"width\":930},\"instanceURI\":\"https://api.labelbox.com/masks/feature/cl4hg2phm00013b6j2thsko0u\"}],\"classifications\":[],\"relationships\":[]}",
"agreement": null,
"benchmarkAgreement": null,
"deleted": false,
"skipped": false,
"project": {
"id": "cl2i6gssn1o2210a3gq549fq0",
"name": "grapes",
"description": ""
},
"dataRow": {
"id": "cl2hzfg8g18kw0ztwbtnq0b6q",
"externalId": "CFR_1620.jpg",
"rowData": "gs://labelbox-193903.appspot.com/ckhmnux5zeutm0825bt0kj34y/5375dc13-6442-22d7-f523-e9d252e715ea-CFR_1620.jpg"
},
"dataset": {
"id": "cl2hz9qay0unl10a3f4wmcsfi",
"name": "data",
"description": ""
},
"user": {
"id": "ckhmnux6hi0p907898jext199",
"email": "[email protected]"
}
},
"user": {
"id": "ckhmnux6hi0p907898jext199",
"email": "[email protected]"
}
}
{
"id": "cl4hghcx72nbd074r35etdcgn",
"createdAt": "2022-06-16T20:09:44Z",
"updatedAt": "2022-06-16T20:11:36Z",
"score": 1,
"deleted": true,
"label": {
"id": "cl4g5555r0ojj07fa025043sh",
"secondsToLabel": 0,
"label": "{\"objects\":[{\"featureId\":\"cl4g5563k00013f6al4spj591\",\"schemaId\":\"cl2i6hbju1o2y10a321w3cusv\",\"title\":\"grape\",\"value\":\"grape\",\"color\":\"#1CE6FF\",\"bbox\":{\"top\":471,\"left\":718,\"height\":246,\"width\":553},\"instanceURI\":\"https://api.labelbox.com/masks/feature/cl4g5563k00013f6al4spj591\",\"classifications\":[{\"featureId\":\"cl4g55ahz00043f6axelsgl1x\",\"schemaId\":\"cl4g551g50p1307ezb2otfmzs\",\"title\":\"test\",\"value\":\"test\",\"answer\":{\"featureId\":\"cl4g55ahz00033f6akoxqn6s3\",\"schemaId\":\"cl4g551g50p1407ezf6x7czou\",\"title\":\"a\",\"value\":\"a\"}}]},{\"featureId\":\"cl4g55d4900063f6aixpq44fx\",\"schemaId\":\"cl2i6hbju1o3010a30ksn2yiy\",\"title\":\"grape mask\",\"value\":\"grape_mask\",\"color\":\"#FF34FF\",\"instanceURI\":\"https://api.labelbox.com/masks/feature/cl4g55d4900063f6aixpq44fx\",\"classifications\":[{\"featureId\":\"cl4g55iqv00083f6aetgrin6j\",\"schemaId\":\"cl4g551g60p1807ez7o5w1mqd\",\"title\":\"text\",\"value\":\"text\",\"answer\":\"test\"}]},{\"featureId\":\"cl4hgh77m00013b6jyhazj23e\",\"schemaId\":\"cl2i6hbju1o2y10a321w3cusv\",\"title\":\"grape\",\"value\":\"grape\",\"color\":\"#1CE6FF\",\"bbox\":{\"top\":238,\"left\":648,\"height\":47,\"width\":568},\"instanceURI\":\"https://api.labelbox.com/masks/feature/cl4hgh77m00013b6jyhazj23e\"}],\"classifications\":[],\"relationships\":[]}",
"agreement": null,
"benchmarkAgreement": null,
"deleted": false,
"skipped": false,
"project": {
"id": "cl2i6gssn1o2210a3gq549fq0",
"name": "grapes",
"description": ""
},
"dataRow": {
"id": "cl2hzfg8g18ks0ztwbh1ohgd5",
"externalId": "CDY_2036.jpg",
"rowData": "gs://labelbox-193903.appspot.com/ckhmnux5zeutm0825bt0kj34y/10043afd-f3a7-6706-8473-9717c482dafd-CDY_2036.jpg"
},
"dataset": {
"id": "cl2hz9qay0unl10a3f4wmcsfi",
"name": "data",
"description": ""
},
"user": {
"id": "ckhmnux6hi0p907898jext199",
"email": "[email protected]"
}
},
"user": {
"id": "ckhmnux6hi0p907898jext199",
"email": "[email protected]"
}
}
{
"organizationId": "cl81imdtk0cie0yx4g39i0du8",
"projectId": "clbxofp0h05d2074475g14f9v",
"action": "APPROVE",
"dataRowIds": [
"cl9elx44f001i076k2pz84tw6"
],
"originTaskId": "92665e1f-a507-4308-bdfc-d6be3c629ec7",
"originTaskName": "My custom review step",
"destinationTaskId": null,
"destinationTaskName": "Done",
"actorId": "cl81imdtx0cif0yx4ak0ndq8a",
"timestamp": "2023-01-20T12:06:01.421Z"
}