Webhooks
Webhooks are available from ftrack version 24.6.
Webhooks are a powerful way to communicate between different systems or services. They enable automatic notifications and data exchange between applications whenever a specific event occurs.
Webhooks operate on a simple principle: callback-based HTTP requests. Instead of continuously polling a server for updates or data, a webhook allows a server to proactively send data to a predefined URL (often referred to as a webhook endpoint) as soon as an event of interest happens. This push-based approach minimizes latency and conserves resources, making webhooks ideal for real-time applications.
When an event triggers, such as a data change, the originating system dispatches an HTTP POST request containing relevant information to the registered webhook URL. The receiving server then processes the payload and executes predefined actions or workflows based on the received data.
Limitations
The current version of webhooks in ftrack have some limitations. As this feature matures some of the limitations may be removed.
- Events are limited to create and update operations. Delete is not yet supported but will be in an upcoming release.
- Only 10 enabled webhooks can exist at the same time.
- Webhook URLs must start with https://
- Webhooks are only supported in the cloud hosted version of ftrack.
- Some operations that happen in background jobs will not trigger events.
- Webhooks are not triggered for private project by default, see separate section about permissions for more details.
Entity events
Events are simple JSON structures that contain information about the entity that generated the event and some metadata.
Entity events contain all the direct properties from the API schemas for the entity in entity.new and entity.old. The event does not contain any data for related entities or computed properties such as URLs. For more information on what entities exist and their properties see the API reference in your workspace. The API reference can be found by clicking on the profile icon in the top left corner and then select Help.
Example payload
{
"id": "a3760d18-0b3e-4d3f-9c75-b730c6e3a80a",
"metadata": {
"date": "2024-02-08T15:47:28.943659+00:00",
"resource_id": "6cb6d7bc-4d03-11ec-bb05-f230d9abde89",
"server_url": "https://my-workspace-url.ftrackapp.com/",
"configuration_hash": "701d735691c1f76f7edb1cb7954a33a7e0adc0e648706a0db043007977fed6b0"
},
"fez_id": "ftrack_entity_event_v1",
"entity": {
"id": [
"3567adcf-794c-4d6f-9645-9d4e1cdb6969"
],
"entity_type": "Task",
"operation": "update",
"new": {
"object_type_id": "11c137c0-ee7e-4f9c-91c5-8c77cec22b2c",
"priority_id": "9661b320-3a0c-11e2-81c1-0800200c9a66",
"id": "3567adcf-794c-4d6f-9645-9d4e1cdb6969",
"bid": 0,
"description": "",
"start_date": null,
"end_date": null,
"status_id": "44ddd0fe-4164-11df-9218-0019bb4983d8",
"type_id": "a750a84f-b253-11eb-ad41-1e003a0c2434",
"project_id": "85a2d78f-6ca6-4787-bd18-0d84da8a6ef9",
"sort": 0,
"context_type": "task",
"name": "Task name",
"parent_id": "85a2d78f-6ca6-4787-bd18-0d84da8a6ef9",
"thumbnail_id": null
},
"old": {
"object_type_id": "11c137c0-ee7e-4f9c-91c5-8c77cec22b2c",
"priority_id": "9661b320-3a0c-11e2-81c1-0800200c9a66",
"id": "3567adcf-794c-4d6f-9645-9d4e1cdb6969",
"bid": 0,
"description": "",
"start_date": null,
"end_date": null,
"status_id": "44dd9fb2-4164-11df-9218-0019bb4983d8",
"type_id": "a750a84f-b253-11eb-ad41-1e003a0c2434",
"project_id": "85a2d78f-6ca6-4787-bd18-0d84da8a6ef9",
"sort": 0,
"context_type": "task",
"name": "Task name",
"parent_id": "85a2d78f-6ca6-4787-bd18-0d84da8a6ef9",
"thumbnail_id": null
}
}
}
Example: Creating a webhook using API
Webhooks can also be created in the ftrack web UI from system settings.
The following example shows how to create a webhook that will be triggered when a task is created:
- Python
- JavaScript
# Create a new automation.
automation = session.create('Automation', {
'name': 'Task created',
})
# Create a trigger.
trigger = session.create('Trigger', {
'automation_id': automation['id'],
'filter': 'entity.entity_type = "Task" and entity.operation = "create"',
})
# Create the webhook.
webhook = session.create('WebhookAction', {
'automation_id': automation['id'],
"webhook_url": "https://my-custom-webhook-url.com",
})
session.commit()
import { operation } from "@ftrack/api";
import { v4 as uuid } from "uuid";
const automationId = uuid();
const operations = [
// Create a new automation.
operation.create("Automation", {
id: automationId,
name: "Task created",
}),
// Create a trigger.
operation.create("Trigger", {
automationId,
filter: 'entity.entity_type = "Task" and entity.operation = "create"',
}),
// Create the webhook.
operation.create("WebhookAction", {
automationId,
webhook_url: "https://my-custom-webhook-url.com",
}),
];
await session.call(operations);
The trigger has a filter that will be evaluated when an event happens in ftrack. If the filter evaluates to true, the webhook will be triggered. The filter operates on the event data and can be used to filter on any data in the event. The whole event is included webhook when sent.
The filter supports basic logical operators like and
, or
, =
and !=
.
The following example shows how to create trigger for when the status of an AssetVersion changes to "Pending Approval":
- Python
- JavaScript
# Get the status id for "Pending Approval".
status_id = session.query(
'select id from Status where name is "Pending Approval"'
).one()['id']
# Create a trigger.
trigger = session.create('Trigger', {
'automation_id': automation['id'],
'filter': f'entity.entity_type = "AssetVersion" and entity.operation = "update" and entity.new.status_id != entity.old.status_id and entity.new.status_id = "{status_id}"',
})
import { v4 as uuid } from "uuid";
// Get the status id for "Pending Approval".
const response = await session.query(
"select id from Status where name is 'Pending Approval'"
);
const statusId = response.data[0].id;
// Create a trigger.
const automationId = uuid();
const trigger = await session.create("Trigger", {
automation_id: automationId,
filter: `entity.entity_type = "AssetVersion" and entity.operation = "update" and (entity.new.status_id != entity.old.status_id) and (entity.new.status_id = ${statusId})`,
});
Permissions and private projects
Webhooks are dispatched via a newly created service user within your workspace, automatically created for this purpose. The permissions assigned to this user dictate whether the webhook is triggered. By default, the service user is authorized to send webhooks to all open projects. To enable webhook delivery to private projects, the webhook user must be explicitly granted access to each private project.
Webhook endpoints
Consider using an existing service as the webhook endpoint such as zapier.com or make.com as they provide plenty of prebuilt integrations with other systems.
Another option which is a bit more developer friendly and a lot cheaper is using AWS Lambda or Google Cloud run. With those services you only pay for the execution time per webhook and you dont have to worry about hosting the service. It still requires that you write and maintain code but you can focus on writing code rather than hosting. See the following repository for an example on how to create a few basic automations using webhooks and Google Cloud Run https://github.com/ftrackhq/cloud-run-webhook-handler
Why use webhooks instead of websocket events?
The main benefit with webhooks is that they integrate well with existing software solutions and reduce the need to run and maintain your own services. They do however provide similar functionality. Generally webhooks provide more out of the box integrations with other systems and allow reacting to events while websocket events allow other types of deeper integrations on the ftrack side such as responding to the user with actions and widgets.