Index
Webhooks allow other systems to notify Slingshot to perform some action.
Currently, we support Flow Production Tracking Webhooks.
This allows Flow to notify Slingshot when specific events occur, so Slingshot can perform actions of its own.
For example, when a user changes a Version status in Flow, a webhook could notify Slingshot and Slingshot could then update the Task and Shot statuses to match.
Configuration¶
webhooks:
update_entity: # (1)!
triggers:
Version/update/sg_status_list: # (2)!
- description: set task to final/pending when version status is set # (9)!
trigger_values: [fnl, pnd] # (3)!
update_entity: SELF # (4)!
update_filters: null # (5)!
update_data: # (6)!
sg_task.Task.sg_status_list: $new_value
multi_entity_update_modes: # (8)!
sg_multientities: set
- description: set shot to final when version is finalled
trigger_values: # (7)!
- fnl
update_entity: SELF
update_filters: null
update_data:
entity.Shot.sg_status_list: fnl
- Currently the only valid webhook type is
update_entity. - See trigger entities
- The webhook will only trigger if the field has changed to one of these values.
IfNone, the webhook will always trigger. - The Entity type to update. If
SELF, it will update the same entity that triggered the webhook. - If
update_entityis notSELF, these filters are used to select which specific entities of typeupdate_entitywill be updated. For filter syntax, see: Shotgrid rest-api - The new values to set on the filtered entities. See update_data
- Each trigger can have as many action blocks as needed to peform different actions for different
trigger_valuesor to update different entities. -
Optional. How to treat updates to multi-entity fields.
Can be
set,add, orremove. The default isset. -
Descriptions are optional and currently only used for our internal reference.
Triggers¶
Trigger definitions are in the format: Entity/event[/field].
Valid events are create, update, delete, and revive.1
For Example:
- Version/update/sg_status_list: triggers when a
Versionsg_status_listfield ischanged. - Shot/create: triggers when a
Shotiscreated
update_data¶
Update data is a dictionary of update entity field: value pairs.
Variables¶
$trigger_entity: the triggering entity dictionary, e.g.{"id": 1, "type": "Version"}$trigger_entity.id: the tiggering entity ID, e.g.1234$trigger_entity.type: the triggering entity type, e.g.Version$tigger_entity.\*: the value of any valid field on the triggering entity$new_value: when event isupdate, the value the field was changed _to$old_value: when event isupdate, the value the field was changed _from$project: the project the entity belongs to, e.g.{"id": 1, "type": "Project"}$user: the user who made the change, e.g.{"id": 1, "type": "HumanUser"}$changed_field: the name of the field that changed, e.g.sg_status_list
Template Examples¶
update_data:
# sets sg_description to "Hello!"
sg_description: Hello!
# sets sg_status_list (Status) to rev (Pending Review)
sg_status_list: rev
# sets the Task status to the value the triggering entity field was just changed to
sg_task.Task.sg_status_list: $new_value
# sets the linked Shot status to Final
entity.Shot.sg_status_list: fnl
Installation in Flow Production Tracking2¶
- In the Flow project, go to the Admin menu and select "Webooks"
- Click on "+Create Webook"
- Add a Name
- Add URL:
(where the Xs are replaced with the show's ID)

- Get "Secret Token" from Geoff (for now)
- Make sure "Validate SSL Certificate" and "Deliver in Batched Format" are both checked
- Under "Notify when unstable" select 'Slingshot Systems'
- Select the appropriate "Project"
- "Entity Type" is usually Shot, Version, Asset, etc.
- You can add as many triggering "Fields" as necessary
- Click "Save"
Common Examples¶
Update Shot and Task Statuses when a Version is Finalled¶
webhooks:
update_entity:
triggers:
Version/update/sg_status_list: # (1)!
- description: set task to final when version is final
trigger_values: # (2)!
- fnl # (3)!
update_entity: Task # (4)!
update_filters: # (5)!
- - sg_versions
- is
- $trigger_entity
update_data:
sg_status_list: fnl # (6)!
- description: set shot to final when version is final
trigger_values: # (7)!
- fnl
update_entity: SELF # (8)!
update_filters: null # (9)!
update_data:
entity.Shot.sg_status_list: fnl # (10)!
- Trigger when a
Version'ssg_status_listfield isupdated - Action #1: set the Task status
- Only trigger when sg_status_list is changed to
fnlspecifically. - Update all
Tasksthat match theupdate_filtersbelow. -
Update all Tasks where the Task's Versions include the
trigger_entity, which in this case is the Version which was just set tofnl.In otherwords, update the Task that contains the triggering version, or in other-otherwords, update the Version's Task.
-
The specific data to update the Task(s) with, in this case we want to also set the task
sg_status_listtofnl. - Action #2: set the Shot status
- Instead of updating the
Shotentity directly and choosing the correct Shot through filters (like we did for Tasks), we're going to updateSELF, which in this case is the triggering Version whose status changed. Either method works. - No need to have filters for
SELFsince we already knowSELFis the specific Version that triggered this event. -
Using deep linking/dot notation, we are able to update the Version's linked Shot's Status field.
So, we're technically updating the Version, but we're updating a deep linked field that is actually the Version's Shot status.
Set sg_date_dropped_in time when sg_di_dropped checkbox is changed¶
webhooks:
update_entity:
triggers:
Shot/update/sg_di_dropped: # (1)!
- description: set date dropped in when di dropped is checked
trigger_values:
- true # (2)!
update_entity: SELF
update_filters: null
update_data:
sg_date_dropped_in: $datetime # (3)!
- description: clear date dropped in when di dropped is unchecked
trigger_values:
- false # (4)!
update_entity: SELF
update_filters: null
update_data:
sg_date_dropped_in: None # (5)!
- Trigger when a
Shot'ssg_di_droppedfield isupdated - Action #1: when checkbox is checked (set to
true) - Set Shot's
sg_date_dropped_infield to current time. - Action #2: when checkbox is unchecked (set to
false) - Set Shot's
sg_date_dropped_infield to None (blank)
Set previous versions to outdated when version is latest¶
webhooks:
update_entity:
triggers:
Version/update/sg_status_list: # (1)!
- description: set old versions outdated when a version is set to latest
trigger_values:
- lav # (2)!
update_entity: Version
update_filters: # (3)!
- - entity
- is
- $trigger_entity.entity
- - sg_task
- is
- $trigger_entity.sg_task
- - sg_status_list
- is
- lav
update_data:
sg_status_list: outv # (4)!
- Trigger when a
Version'ssg_status_listfield isupdated - Only trigger when the new status value is
lav(Latest) - Find all Versions of the same Entity Link (e.g. Shot) and Task as the triggering Version and also have the status
lav(Latest) - Set those Versions statuses to
outv(Outdated) 5.
Add vendor to a Shot when it's set on a Version¶
webhooks:
update_entity:
triggers:
Version/update/user: # (1)!
- description: add vendor to shot when it's set on version
trigger_values: null
update_entity: SELF
update_filters: null
update_data:
entity.Shot.sg_vendor_groups: # (2)!
- $new_value
multi_entity_update_modes:
entity.Shot.sg_vendor_groups: add # (3)!
- description: remove vendor from shot when it's removed from version
trigger_values: [null] # (4)!
update_entity: SELF
update_filters: null
update_data:
entity.Shot.sg_vendor_groups: # (5)!
- $old_value
multi_entity_update_modes:
entity.Shot.sg_vendor_groups: remove # (6)!
- Trigger when a
Version'suserfield isupdated - Update the linked Shot's
sg_vendor_groupsfield with the new_value -
Since
sg_vendor_groupsis a multi-entity field, we specify that we want toadd$new_valueto the list of sg_vendor_groups.Without this it would default to
set, which would replaces all sg_vendor_groups with only$new_value -
If
$new_valueis null (a vendor was removed from a Version), we need to remove the vendor from the Shot as well. - This time, we update
sg_vendor_groupswith theold_value - ...and set
multi_entity_update_mode toremove, which will remove$old_value` from the current sg_vendor_groups.
Final Shot when all Tasks are final¶
This example is a little tricky, we want to update the triggering Task but only if all tasks are final. So, we filter on the triggering task's id, which will only ever match the triggering Task, but we also add additional filters to check fields of other linked entities. So, our filters will only ever match either the triggering Task, or nothing (in which case no updates occur.)
webhooks:
update_entity:
triggers:
Task/update/sg_status_list: # (1)!
- description: final shot when all tasks are final
trigger_values: ["fin", "omt"] # (2)!
update_entity: Task
update_filters: [
["id", "is", $trigger_entity.id], # (3)!
[
"entity.Shot.tasks.Task.sg_status_list", # (4)!
"not_in",
["wtg", "ip", "hld"], # (5)!
],
]
update_data: { "entity.Shot.sg_status_list": "fin" } # (6)!
- Trigger when a
Task'ssg_sg_status_listfield isupdated -
Action #1: when status is set to
finoromt(When a Task is omitted, we still want to final the Shot if all the other Tasks are final.)
-
Match the Task with the same id as our triggering entity. Normally you could just use
SELF, but in this case we need to add additional filters on the next line. - We know the triggering task's status is
finoromt, but we need to check the statuses for all tasks that belong to this Task's shot. We can do that with this deep linked field, which finds the triggering Task's linked Shot, then that Shot's tasks (plural), and makes sure none of the Tasks' statuses are in the list. -
If no task statuses are in this list, we assume they're all
finoromt. We have to usenot_ininstead ofin.If we checked if that status was
in[fin, omt]instead, it would match if any of the Shot's tasks are final, but we need it to only match if all of the Shot's tasks are final, so we have to do this negative check. -
Update the matched task (if any)'s Shot status to
fin
Debugging¶
There are many places where a webhook can go wrong. The first step is to check the Webhooks page in Shotgrid to make sure the Webhook triggered and was sent to our system.
todo: screenshot
The response tab should say "Webhook delivery received." It it doesn't, then our system did not accept the webhook at all. Possibly the Webhook URL is misformed, or some other backend error occurred.
todo: screenshot
Once we are sure our system received the webhook, we can check for more details in the Logfire logs, or back in Shotgrid, view the result in the Acknowlegement section of the Request tab:
todo: screenshot
Configuration or other errors will usually display here in this Acknowledgement for convenience.
-
Flow Production Tracking Webhooks Guide - When do Lifecycle Events Occur? ↩
-
Flow Production Tracking Webhooks Guide - Creating a Webhook ↩
