Skip to main content

Webhooks

How to set up webhooks within Creative Force, including details on events and example payloads.

Tejs Rasmussen avatar
Written by Tejs Rasmussen
Updated over a week ago

Webhook configuration provides filtering controls to reduce unnecessary event traffic and improve delivery performance. You can select specific webhook events, filter by Workspace and Production Step, and configure settings through organized tabs.


Setting Up a Webhook

Creating a webhook is a two-step process. You'll first need to set up how you want your webhook to behave through CreativeForce - what events should it listen to. After that, you'll set up your server to receive and manage the payload.

To set up a webhook, go to the “Studio settings” page via the menu in the top right corner, and click on "Integration" and from there on the sub-menu "Webhooks":

From there, click "Add Webhook." Webhooks require a few configuration options before you can make use of them.

The webhook configuration screen is organized into three tabs: Settings, Filters, & Custom Headers.

Settings: Configure basic webhook details (Payload URL, Secret, Events)

Filters: Set up filtering by Workspace and Production Step.

Custom Headers: Add custom headers to webhook requests

We'll go through each of these in the sections below.

Settings Tab

Configuration Option

Notes

Payload URL

The Payload URL is the URL of the server that will receive the webhook requests.

This URL must be HTTPS, and can not be an IP (private IP or public IP).

The URL can't contain: localhost, creativeforce.io, metadata.google, burpcollaborator.net, .local, .internal, ram.aliyuncs.com, fuf.me, localtest.me, ulh.us

Good Payload URL Example

Bad Payload URL Example:

https://localhost:4567/payload

http://localhost:8000/payload

Secret Key

When your secret key is set, Creative Force uses it to create a hash signature with each payload.

This hash signature is passed along with each request in the headers as X-CF-Signature.

The format of the secret key is Base64 RFC 2045

For more information, see the section on validating webhooks further down in this article.

Trigger Events

Events are at the core of webhooks. The webhooks fire whenever a certain action is taken, either by users or the Creative Force system.

Your server (payload URL) will intercept and act upon these.

You can select from 7 different event groups, shown in the next table.

Events to Trigger Webhooks

Event Category

Available Events

Product Events

  • Reset

  • StatusChanged

  • StyleGuideChanged

  • CategoryChanged

  • Product Deactivated

  • ColorReferenceMigrated

  • PropertiesUpdated

  • Deleted

  • Activated

  • ProductStatusChangedviaKelvin

  • StyleguideChangedviaKelvin

  • CategoryChangedviaKelvin

  • ProductIgnoredviaKelvin

  • PropertiesUpdatedviaKelvin

  • ProductDeletedviaKelvin

  • ProductActivatedviaKelvin

  • EnableProductionType

  • DisableProductionType

  • ProductImported

  • ColorReferenceCreated

  • ColorReferenceUpdated

  • ColorReferenceDeleted

  • ProductCompleted

  • MoveToAnotherJob

  • ApplyUpdates

  • ProductAddedtoBundle

  • ProductRemovedfromBundle

  • ProductTriggeredCopywriting

  • ProductDeliveredCopywriting

  • ProductDeliveryCopywritingFailed

  • ProductIgnoreDeliverCopywriting

Sample Events

  • LocationChanged

  • Addedtocontainer

  • Releasedfromcontainer

  • Checked-in

  • Checked-out

User Events

  • UserLoggedIn

  • UserLoggedOut

  • PasswordChanged

  • AvatarUpdated

  • UserInvitationCompleted

  • UserUpdated

  • UserDeleted

  • UserInvitationDeleted

  • UserDisabled

  • UserEnabled

  • UserInvited

  • UserRe-Invited

  • ProductVendorAdded

  • StudioSign-UpCompleted

  • UserInvitationCompleted

  • UserInvitationDeleted

  • SettingMigrateColorReference(Ecomm)

  • SettingSourceE-Comm ColorReference(Editorial)

Task Events

  • Completed

  • Created

  • Started

  • Bypassed

  • Reset

  • Assigned

  • Unassigned

  • Rejected

  • Approved

  • WaitingforColorReference

  • ProcesswithoutColorReference

  • Failed

  • CopywritingTaskEditMade

  • ReadyToWork

  • TaskSoftRejected

  • CopywritingDreemGenerateText

  • CopywritingDreemAdjustText

Production Events

  • WorkUnitStatusChanged

  • WorkUnitReset

  • WorkUnitEnabled

  • WorkUnitDisabled

  • WorkUnitChangedSource

  • WorkUnitCompleted

  • WorkUnitBypassExternalPost

  • WorkUnitChangePostVendor

  • WorkUnitCreated

  • WorkUnitDeleted

  • CopywritingProductionLayoutStateChanged

Job Events

  • StatusChanged

  • Created

  • Updated

  • Deleted

  • DeadlineUpdated

Session Events

  • AddToSession

  • RemovedfromSession

When you're finished, click Save. Now that you created the webhook, it's time to set up our server to test the webhook.

Filters Tab

The Filters tab allows you to refine when webhooks are triggered. Filtering by Workspace and Production Step reduces webhook volume, improves delivery performance, and minimizes load on receiving systems.

This is particularly useful in high-volume production environments.

Workspace

Filter webhook events by specific Workspaces. Only events from selected Workspaces will trigger the webhook.

  • Select one or multiple Workspaces from the list.

  • Enable 'All Workspace Access' to receive events from all Workspaces.

Production Step

For task-related events, filter by Production Step to control which task events trigger your webhook.

📝 Note: Production Step filtering is only available when Task Events are selected.

Available Production Steps:

  • Capture

  • Final Selection

  • Photo Review

  • Digital Processing

  • External Post

  • External Post QC

  • Internal Post

  • Internal Post QC

  • Post Review

  • Copywriting

  • Copywriting QC

  • Cloud Automation

  • Cloud Automation QC

  • Asset Delivery

Custom Headers Tab

Add custom HTTP headers to your webhook requests for additional authentication or routing needs.

Delivery Headers

HTTP POST payloads that are delivered to your webhook's configured URL endpoint will contain several special headers:

Header

Description

X-CF-Event

Name of the event that triggered the delivery. For example “Task completed”, “User created”.

X-CF-Signature

The HMAC hex digest of the response body. See the section about validating the webhook later in this document.

Product Webhooks

Key

Type

Description

Action

String

The action that was performed.

Appears as one of the following:

  • Reset

  • StatusChanged

  • StyleGuideChanged

  • CategoryChanged

  • Ignored

  • ColorReferenceMigrated

  • PropertiesUpdated

  • Deleted

  • Activated

Actor

Object

The user or the actor that triggered the event.

Note: We will send the UserID only, not the user name.

PayloadId

String

ID of the payload (GUID)

EventGroupName

String

The event group triggered. Value: product

EventDatetimeUtc

Long

Unix Timestamp (milliseconds) - the number of milliseconds since the Unix Epoch

JobId

String

ID of the job (GUID)

JobCode

String

Job code

ClientId

String

ID of the client (GUID).

ClientName

String

Client name

ProductId

String

ID of the product (GUID)

ProductCode

String

Product code

ProductStatusId

Int

Product Unit Status ID

ProductStatusName

String

Product Unit Status Name

Webhook Payload Example:

When a user resets a Product, the webhook payload would appear as shown below.

{
"Action":"ProductReset",
"Actor":{
"UserId":"19e62847-f302-4e32-9e4a-b6d8c304fcbe"
},
"PayloadId":"c02f0f73-1706-4973-9a4d-38007d6685e9",
"EventGroupName":"product",
"EventDatetimeUtc":1595204418000,
"JobId":"d84eef10-c8a6-437a-9f95-0b58d2a3cb38",
"JobCode":"Summer 2020",
"ClientId":"2c856b2f-aded-4609-bf67-27009603b2b9",
"ClientName":"My Big client",
"ProductId":"7a782d57-b0bf-4743-8f02-2b1a1e229869",
"ProductCode":"AW2130146"
}

Sample Webhooks

Key

Type

Description

Action

String

The action that was performed.

Appears as one of the following:

  • LocationChanged

  • AddedToContainer

  • ReleasedFromContainer

  • Checked-in

  • Checked-out

Actor

Object

The user or the actor that triggered the event.

Note: We will send the UserID only, not the user name.

PayloadId

String

ID of the payload (GUID)

EventGroupName

String

The event group triggered. Value: sample

EventDatetimeUtc

Long

Unix Timestamp (milliseconds) - the number of milliseconds since the Unix Epoch

ClientID

String

ID of the Client (Workspace) where the Sample originated

SampleId

String

ID of the Sample (GUID)

SampleCode

String

Sample Code

LocationId

String

ID of the location (GUID)

LocationName

String

Location name

SubLocationId

String

ID of the sub-location (GUID)

SubLocationName

String

Sub-location name

Products

Array

An array of ID of the product ID (GUID) and Product code.

If there is no product, then return an empty array.

products: [{productId: "", productCode: ""},....}

Webhook Payload Example:

When a user checks in a Sample, the payload would appear as shown below.

{
"ClientId": "719bee19-f630-455a-8f00-2f1331fd4a98"
"SampleId": "4666fcd0-0179-44d8-a66d-bc65a4acd968",
"SampleCode": "88829384",
"LocationId": "ee410fb0-6a99-4b0e-a95e-83abe6aa5a5e",
"LocationName": "CF Center",
"SubLocationId": "00000000-0000-0000-0000-000000000000",
"SubLocationName": "",
"Products": [{
"ProductId": "ef0533fc-a11c-43a2-ab84-1c9bdabc9e7f",
"ProductCode": "ADROAN-830"
}
],
"PayloadId": "5385f2a9-88da-4c38-88a5-5f6f875ecb74",
"EventGroupName":"sample",
"EventDatetimeUtc": 1601969236991,
"Action": "Checked-in",
"Actor": {
"UserId": "205c0bbd-ea29-4250-87f5-bdb254a91075"
}
}



User Webhooks

Key

Type

Description

Action

String

The action that was performed.

Appears as one of the following:

  • UserLoggedIn

  • UserLoggedOut

  • PasswordChanged

  • AvatarUpdated

  • ProductVendorAdded

  • UserUpdated

  • UserDeleted

  • UserDisabled

  • UserEnabled

  • UserInvited

Actor

Object

The user or the actor that triggered the event.

Note: We will send the UserID only, not the user name.

PayloadId

String

ID of the payload (GUID)

EventGroupName

String

The event group triggered. Value: user

EventDatetimeUtc

Long

Unix Timestamp (milliseconds) - the number of milliseconds since the Unix Epoch

UserId

String

ID of the user (GUID) Notes: We will send UserID only, no user name.

Webhook Payload Example:

When a user logs in, the payload would appear as shown below.

{
"Action":"UserLoggedIn",
"Actor":{
"UserId":"19e62847-f302-4e32-9e4a-b6d8c304fcbe"
},
"PayloadId":"c02f0f73-1706-4973-9a4d-38007d6685e9",
"EventGroupName":"user",
"EventDatetimeUtc":1595204418000,
"UserId":"19e62847-f302-4e32-9e4a-b6d8c304fcbe",
}

Task Webhooks

Key

Type

Description

Action

String

The action that was performed.

Appears as one of the following:

  • Reset

  • Completed

  • Started

  • ReadyToWork

  • Bypassed

  • Assigned

  • Unassigned

  • Rejected

  • Approved

Actor

Object

The user or the actor that triggered the event.

Note: We will send the UserID only, not the user name.

PayloadId

String

ID of the payload (GUID)

EventGroupName

String

The event group triggered. Value: task

EventDatetimeUtc

Long

Unix Timestamp (milliseconds) - the number of milliseconds since the Unix Epoch

TaskId

String

ID of the task (GUID)

Assignee

Object

The assignee of this task. Notes: We will send UserID only, no user name.

JobId

String

ID of the job (GUID)

JobCode

String

Job code

ClientId

String

ID of the client (GUID).

ClientName

String

Client name

ProductId

String

ID of the product (GUID)

ProductCode

String

Product code

StepId

Int

ID of the step

StepName

String

Step name

StepStatusId

Int

ID of the Step Status

StepStatusName

String

Step Status name

ShootingTypeId

Int

ID of the Shooting type (aka Production type)

ShootingTypeName

String

Shooting type name (aka Production type name)

StyleGuideId

String

ID of the Style guide

StyleGuideName

String

Style guide name

WorkflowId

String

ID of the Workflow

WorkflowName

String

Workflow name

WorkUnitId

String

ID of the WorkUnit (GUID)

Webhook Payload Example:

When a Photography task is completed, the payload would appear as shown below.

{
"Action":"completed",
"Actor":{
"UserId":"19e62847-f302-4e32-9e4a-b6d8c304fcbe"
},
"PayloadId":"c02f0f73-1706-4973-9a4d-38007d6685e9",
"EventGroupName":"task",
"EventDatetimeUtc":1595204418000,
"TaskId":"c02f0f73-4665-4aae-aac1-c2fbc65365de",
"Assignee":{
"UserId":"19e62847-f302-4e32-9e4a-b6d8c304fcbe"
},
"JobId":"d84eef10-c8a6-437a-9f95-0b58d2a3cb38",
"JobCode":"Summer 2020",
"ClientId":"2c856b2f-aded-4609-bf67-27009603b2b9",
"ClientName":"My Big client",
"ProductId":"7a782d57-b0bf-4743-8f02-2b1a1e229869",
"ProductCode":"AW2130146",
"StepId":"3",
"StepName":"Photography",
"StepStatusId":"9000",
"StepStatusName":"Done",
"ShootingTypeId":"1",
"ShootingTypeName":"On Model",
"WorkflowId":"2b5d3e1b-1706-4973-9a4d-57ab7d6685e9",
"WorkflowName":"My first workflow",
"StyleGuideId":"2376b9cb-67db-490f-a5e8-89811ed6b087",
"StyleGuideName":"Summer on the beach 2020"
}

Work Unit Webhooks

Key

Type

Description

Action

String

The action that was performed.

Appears as one of the following:

  • WorkUnitStatusChanged

  • WorkUnitReset

  • WorkUnitEnabled

  • WorkUnitDisabled

  • WorkUnitChangedSource

  • WorkUnitCompleted

  • WorkUnitBypassExternaPost

  • WorkUnitChangePostVendor

Actor

Object

The user or the actor that triggered the event.

Note:

  • We will send the UserID only, not the user name.

  • In some cases when data is updated by a background service, the Actor will be empty.

* Sync from data source: create/delete product

PayloadId

String

ID of the payload (GUID)

EventGroupName

String

The event group triggered. Value: work unit

EventDatetimeUtc

Long

Unix Timestamp (milliseconds) - the number of milliseconds since the Unix Epoch

ClientId

String

ID of the client (GUID).

ClientName

String

Client name

ProductId

String

ID of the product (GUID)

ProductCode

String

Product code

ProductionTypeId

Int

Production Type ID

ProductionTypeName

String

Production Type Name

WorkUnitStatusId

Int

Work Unit Status ID after change

WorkUnitStatusName

String

Work Unit Status Name after change

WorkUnitId

String

ID of the WorkUnit (GUID)

Webhook Payload Example:

When a production's status changes, the payload would appear as shown below.

{
"Action":"StatusChanged",
"Actor":{
"UserId":"19e62847-f302-4e32-9e4a-b6d8c304fcbe"
},
"PayloadId":"c02f0f73-1706-4973-9a4d-38007d6685e9",
"EventGroupName":"work unit",
"EventDatetimeUtc":1595204418000,
"ClientId":"2c856b2f-aded-4609-bf67-27009603b2b9",
"ClientName":"My Big client",
"ProductId":"7a782d57-b0bf-4743-8f02-2b1a1e229869",
"ProductCode":"AW2130146"
"ProductionTypeId":1,
"ProductionTypeName":"OnModel"
"WorkUnitStatusId":3000
"WorkUnitStatusName":"InProgress"
}

Job Webhooks

Key

Type

Description

Action

String

The action that was performed.

Appears as one of the following:

  • Created

  • Updated

  • Deleted

  • StatusChanged

  • Deadline Updated

Actor

Object

The user or the actor that triggered the event.

Note: We will send the UserID only, not the user name.

PayloadId

String

ID of the payload (GUID)

EventGroupName

String

The event group triggered. Value: Job

EventDatetimeUtc

Long

Unix Timestamp (milliseconds) - the number of milliseconds since the Unix Epoch

JobId

String

ID of the job (GUID)

JobName

String

Job name

JobCode

String

Job code

JobStatusId

Int

Job Unit Status ID

JobStatusName

String

Job Unit Status Name

ClientId

String

ID of the client (GUID)

ClientName

String

Client Name

JobDeadlineUtc

Long

Unix Timestamp (milliseconds) - the number of milliseconds since the Unix Epoch

Webhook Payload Example:

When a job is deleted, the payload would appear as shown below.

{
"Action":"Deleted",
"Actor":{
"UserId":"19e62847-f302-4e32-9e4a-b6d8c304fcbe"
},
"PayloadId":"c02f0f73-1706-4973-9a4d-38007d6685e9",
"EventGroupName":"Job",
"EventDatetimeUtc":1595204418000,
"JobId":"d84eef10-c8a6-437a-9f95-0b58d2a3cb38",
“JobName:”Summer 2020”,
"JobCode":"Summer 2020”,
“JobStatusId”:3000,
“JobStatusName”:”In Progress”,
"ClientId":"2c856b2f-aded-4609-bf67-27009603b2b9",
"ClientName":"My Big client",
“JobDeadlineUtc”:1595204529000,
}

Session Webhooks

Key

Type

Description

Action

String

The action that was performed.

Appears as one of the following:

  • AddedToSession

  • RemovedFromSession

Actor

Object

The user or the actor that triggered the event.

Note: We will send the UserID only, not the user name.

PayloadId

String

ID of the payload (GUID)

EventGroupName

String

The event group triggered. Value: session

EventDatetimeUtc

Long

Unix Timestamp (milliseconds) - the number of milliseconds since the Unix Epoch

ProductId

String

ID of the product (GUID)

ProductCode

String

Product code

ShootingTypeId

Int

ID of the Shooting type (aka Production type)

ShootingTypeName

String

Shooting type name (aka Production type name)

WorkUnitId

String

ID of the WorkUnit (GUID)

ClientId

String

ID of the Client (Workspace) assigned to the Session, as applicable.

SessionId

String

ID of the Session (GUID)

SessionCode

String

Session Code

SessionName

String

Session Name

PlannedTimeSlot

JSON Literal

Time of Session

PlannedTeam

JSON Literal

PlannedTeam consists of individuals participating in that session, specifies who they are, and their respective roles.

PlannedProducerId

String

ID of the Planned Producer (GUID)

PlannedProducerName

String

Planned Producer Name

PlannedSetId

String

ID of the Planned Set (GUID)

ProductionItemId

String

ID of the Production Item (GUID)

PlanningStatus

JSON Literal

Status (ID, Name) of the Planning

Appears as one of the following:

  • Unplanned = 2

  • Planned = 1

ActionSource

String

The application that triggered the event.

Webhook Payload Example:

When a session is added to, the payload would appear as shown below.

{
"ActionSource": "AddFromGateway",
"ClientId": "07a2a5cb-7525-4e7b-b032-3f647a8a068c",
"SessionId": "cba7640d-452b-417b-8bbc-aaa92a763359",
"SessionCode": "SES113736CF",
"SessionName": "Quyen Test Add session",
"PlannedTimeSlot": "[{\"PlannedStart\":\"2023-12-10T01:00:00\",\"PlannedEnd\":\"2023-12-10T10:00:00\"}]",
"PlannedTeam": "{\"Assistant\":\"phuonglth+dev@creativeforce.io,dungnt+sing@creativeforce.io\",\"Photographer\":\"hanh@creativeforce.io\",\"HairAndMakeup\":\"duongvtt+dev@creativeforce.io\",\"DigitalProcessing\":\"hanttn@creativeforce.io\"}",
"PlannedProducerId": "429f37e8-4583-4541-89d9-49230bbf046f",
"PlannedProducerName": "DuongVTT DEV",
"PlannedSetId": "53c4bc2d-244a-490e-9f75-e3554246b6dd",
"ProductionItemId": "1e6b01e0-671e-462c-b266-692d6a16eb92",
"PlanningStatus": "{\"PlanningStatusId\":2,\"PlanningStatus\":\"Unplanned\"}",
"WorkUnitId": "1e6b01e0-671e-462c-b266-692d6a16eb92",
"ShootingTypeId": 1,
"ProductId": "99ecc381-41f1-4782-bcd4-e762e50a8a93",
"ProductCode": "Product_230831_5",
"PayloadId": "d483e7cb-e03b-4ccd-b307-22ca3e990e96",
"EventGroupName": "session",
"EventDatetimeUtc": 1701935735820,
"Action": "AddedToSession",
"Actor": {
"UserId": "600a5a14-8bd5-4d48-888e-f2b0bf2defc8"
}
}

Validating Webhooks


Step 1: Hash JSON Payload


Validate webhooks in your application by hashing the JSON payload of the webhook using the SHA256 algorithm. This will require the secret key generated when you first set up the webhook in Gamma.

Step 2: Compare to Webhook Signature

Then, you can compare the hash with the webhook signature. If they match, the webhook can be trusted.

📝 Notes:

  • The X-CF-Signature is 32 bytes and in hexa format. It's therefore important to make sure your hash function is returning 32-byte hexa as well.

  • Using a plain == operator is not advised. A method like secure_compare performs a "constant time" string comparison, which renders it safe from certain timing attacks against regular equality operators.

Example:

Below is an example of this process. The example is written in Ruby for a Sinatra server, but it should give you a good idea of the approach.

require 'sinatra'
require 'json'

post '/payload' do
request.body.rewind
payload_body = request.body.read

verify_signature(payload_body)

push = JSON.parse(payload_body)
puts "I got callback, JSON: #{push}"

return halt 200, "OK"
end

def verify_signature(payload_body)
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('SHA256'), ENV['SECRET_TOKEN'], payload_body)
return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_CF_SIGNATURE'])
end

Security

Below are a few various callouts for security-related items to be aware of.

Security Feature

Notes

Content Type

Creative Force always uses application/json as the content type.

Enable/Disable

You can choose to disable a webhook if you want to pause it temporarily.

Retry

The CF system will POST data to the payload URL specified and expects a 2xx HTTP status code return.

If no 2xx HTTP status is returned, the system will automatically retry up to 3 times. Each retry triggers after 5 to 10 minutes.

Did this answer your question?