Receiving Callbacks
Fastevo sends callbacks to notify you about various events related to your project. Callbacks can be configured at a project level through the Fastevo web panel or via API calls.
We recommend using a secret URL to receive callbacks. For security purposes, the URL must use the HTTPS protocol. If needed, you can include a token as a query parameter in the URL.
Managing Webhooks
You can manage webhooks for receiving callbacks through the Fastevo API. This includes creating, deleting, and listing webhooks.
Creating or Updating a Webhook
To create or update a webhook, you need to perform a POST request to the following endpoint:
POST https://api.fastevo.net/api/v1/projects/mediaProtection/configurations/general/webhooks
The request body should include the following parameters:
webhookUrl
(mandatory): The URL where the webhook will send the callbacks.events
(mandatory): An array of event types that the webhook should listen to. You can use*
to listen to all events.
Possible Events to Subscribe
Here are the possible events you can subscribe to for webhook notifications:
siemRuleCreated
: Triggered when a new SIEM rule is created.siemRuleUpdated
: Triggered when an existing SIEM rule is updated.siemRuleDeleted
: Triggered when an SIEM rule is deleted.contentStatusChanged
: Triggered when the status of content changes.contentCreated
: Triggered when new content is created.contentDeleted
: Triggered when content is permanently deleted from the system.contentTrashed
: Triggered when content is moved into the trash (pendingDeletion).contentRestored
: Triggered when content is restored from trash.upsertedWebhook
: Triggered when a webhook is created or updated.deletedWebhook
: Triggered when a webhook is deleted.*
: Wildcard event to listen to all events.
Example Request
{
"webhookUrl": "https://yourdomain.com/webhook",
"events": ["contentCreated", "contentStatusChanged"]
}
API Response
After successfully creating or updating the webhook, the API will return a response with a status code of 201
and a JSON body indicating success.
Example Success Response
{
"success": true
}
Deleting a Webhook
To delete a webhook, you need to perform a DELETE request to the following endpoint:
DELETE https://api.fastevo.net/api/v1/projects/mediaProtection/configurations/general/webhooks
The request body should include the following parameter:
webhookUrl
(mandatory): The URL of the webhook to be deleted.
Example Request
{
"webhookUrl": "https://yourdomain.com/webhook"
}
API Response
After successfully deleting the webhook, the API will return a response with a status code of 204
.
Listing Webhooks
To retrieve a list of all configured webhooks, you need to perform a GET request to the following endpoint:
GET https://api.fastevo.net/api/v1/projects/mediaProtection/configurations/general/webhooks
API Response
The API will return a response with a status code of 200
and a JSON body containing the list of webhooks.
Example Response
{
"webhooks": [
{
"url": "https://yourdomain.com/webhook",
"events": ["contentCreated", "contentStatusChanged"]
}
]
}
Callback Structure
When Fastevo sends a callback, it sends a JSON object with a specific structure. Here's an example of a callback:
{
"type": "notification",
"subject": "MP2",
"messageId": "d54cb8fd-9494-47c2-8b46-cd3c8a58cd5c",
"timestamp": "2024-03-07T16:33:39.845Z",
"message": "{\"records\":[{\"eventSource\":\"65e9e86c9bb6cadccf0849be\",\"eventName\":\"contentDeleted\",\"eventTimestamp\":\"2024-03-07T16:33:39.028Z\",\"eventDetails\":{\"contentId\":\"65e9ea09222e51cb6cbc60eb\"}},{\"eventSource\":\"65e9e86c9bb6cadccf0849be\",\"eventName\":\"contentDeleted\",\"eventTimestamp\":\"2024-03-07T16:33:39.031Z\",\"eventDetails\":{\"contentId\":\"65e9ebea7e44f19fff715352\"}}]}",
"signature": "snQ4Cx4bvon7nZwc/4FsoqT2/AdbDQYCMwxRptUO565gwfz9XSQh6XZ6f22O6580JpY4n5aPJJGcLd79X8Fvjjm0Rvarrehj0rQSwjM94tENwyRzRELsU3Z6eopczHhfiW/IyPYxkQYc1hKT2D8YLQBZ2RQgY5G8X1qha3Vi/9y6C0CPQKDWW7FeGSw1177Wy+o0xjEItEIujWdKK6UDJ/IxhkzAFIho82txR1XqL7lVj5x7kaWePq2txyKNnQUcC1+Nlfk7RyvnuAB0XhYT7LP0T6Yb6SlC22LNKBVv3KWiBWJRu9kUolQdrNVeMBhzDkSubyU1TMYYc50OXZSoyw==",
"signatureVersion": "1",
"publicKeyURL": "https://fastevo.com/identity/public_key.pem"
}
Let's break down each field:
type
: This field indicates the type of the callback. In this case, it's anotification
.subject
: This field indicates the service that is sending the callback. For Fastevo Media Protection Platform, it will be "MP2".messageId
: This field is a unique identifier for the callback.timestamp
: This field indicates when the callback was sent.signature
: This field is used to verify the authenticity of the message. It's generated by Fastevo and can be verified using the public key provided in thepublicKeyURL
field.signatureVersion
: This field indicates the version of the signature. Currently, it's "1".publicKeyURL
: This field provides the URL where you can find the public key to verify the signature.
The message
field contains the actual event data. It's a stringified JSON object that needs to be parsed to be used. Inside the parsed message
object, there's a records
field, which is an array of event objects.
Each event object inside the records
array has the following fields:
eventSource
: This is the projectId of the originating project.eventName
: This is the name of the event.eventTimestamp
: This is the time when the event occurred.eventDetails
: This field contains additional details about the event. The content of this field varies depending on theeventName
.
Verifying the Signature
Verifying the signature is an optional but recommended step. It ensures the authenticity of the callback. To speed up the process, consider storing a local copy of Fastevo's public signing key.
The signature
field is used to verify the authenticity of the callback. Here's how you can do it:
First, you need to create a string that includes the message
, messageId
, subject
, timestamp
, and type
fields, each followed by a newline character. Then, you use this string to verify the signature
using the public key provided in the publicKeyURL
field.
Here's a code sample that demonstrates this process:
import crypto from "crypto";
async function verifySignature(notificationObject, publicKey) {
const fieldsForSignature = [
"message",
"messageId",
"subject",
"timestamp",
"type",
];
let stringToSign = "";
const verify = crypto.createVerify("sha1");
for (const field of fieldsForSignature) {
stringToSign += `${field}\n${notificationObject[field]}\n`;
}
verify.update(stringToSign);
verify.end();
const isValidSignature = verify.verify(
publicKey,
notificationObject.signature,
"base64"
);
return isValidSignature;
}
In this code, notificationObject
is the parsed JSON object of the callback, and publicKey
is the public key obtained from the publicKeyURL
.
Event Details
Now that we've explained the general structure of the callback and how to verify its authenticity, let's move on to explain the different types of events and their details.
Event: siemRuleCreated
This event is triggered when a new SIEM rule is created.
Demo JSON:
{
"eventName": "siemRuleCreated",
"eventDetails": {
"ruleId": "1234abcd5678efgh"
}
}
Event Details:
ruleId
: The unique identifier of the created SIEM rule.
Event: siemRuleUpdated
This event is triggered when an existing SIEM rule is updated.
Demo JSON:
{
"eventName": "siemRuleUpdated",
"eventDetails": {
"ruleId": "1234abcd5678efgh"
}
}
Event Details:
ruleId
: The unique identifier of the updated SIEM rule.
Event: siemRuleDeleted
This event is triggered when an SIEM rule is deleted.
Demo JSON:
{
"eventName": "siemRuleDeleted",
"eventDetails": {
"ruleId": "1234abcd5678efgh"
}
}
Event Details:
ruleId
: The unique identifier of the deleted SIEM rule.
---
### Event: `contentTrashed`
This event is triggered when content has been moved into the trash. At this point, the content is in a `pendingDeletion` status but is not permanently removed. For more details, see the [Content Trash documentation](/mp2/content-trash).
**Demo JSON:**
```json
{
"eventName": "contentTrashed",
"eventDetails": {
"contentId": "65ea2671a604d3b574ed632c"
}
}
Event Details:
contentId
: The unique identifier of the content that has been moved to trash.
Event: contentRestored
This event is triggered when previously trashed content is restored from the trash back into an active status.
Demo JSON:
{
"eventName": "contentRestored",
"eventDetails": {
"contentId": "65ea2671a604d3b574ed632c"
}
}
Event Details:
contentId
: The unique identifier of the content that has been restored from trash.
Event: contentDeleted
This event is triggered when content has been permanently deleted from the system (i.e., it has passed through trash or it was pendingUpload or queued when deleted).
Demo JSON:
{
"eventName": "contentDeleted",
"eventDetails": {
"contentId": "65ea12190350c7c3ee9333da"
}
}
Event Details:
contentId
: The unique identifier of the content that has been deleted.
Event: contentCreated
This event signifies that new content has been created within Fastevo.
Demo JSON:
{
"eventName": "contentCreated",
"eventDetails": {
"contentId": "65ea1ea3efc38c1b63573266"
}
}
Event Details:
contentId
: The unique identifier of the newly created content.
Event: contentStatusChanged
to queued
This event signifies that the content has been queued for processing. It is triggered when the content is successfully uploaded and is waiting in line to be processed.
Demo JSON:
{
"eventName": "contentStatusChanged",
"eventDetails": {
"contentId": "65ea12190350c7c3ee9333da",
"status": "queued"
}
}
Event Details:
contentId
: The unique identifier of the content that has been queued for processing. This ID can be used to track the status of the content throughout the processing pipeline.status
: The new status of the content. In this case, it'squeued
, indicating that the content is in the processing queue and will be processed as soon as resources are available.
Event: contentStatusChanged
to processing
This event indicates that the content has entered the processing stage.
Demo JSON:
{
"eventName": "contentStatusChanged",
"eventDetails": {
"contentId": "65ea12190350c7c3ee9333da",
"status": "processing"
}
}
Event Details:
contentId
: The unique identifier of the content that is being processed.status
: The new status of the content. In this case, it'sprocessing
, indicating that the content is currently being processed.
Event: contentStatusChanged
to error
This event is triggered when an error occurs during content processing.
Demo JSON:
{
"eventName": "contentStatusChanged",
"eventDetails": {
"contentId": "65ea155d6cba195b04c51c4f",
"status": "error",
"statusDetails": "genericError"
}
}
Event Details:
contentId
: The unique identifier of the content that encountered an error during processing.status
: The new status of the content. In this case, it'serror
, indicating that an error occurred during processing.statusDetails
: This field contains a brief description or code indicating the type of error encountered. In this example, aGenericError
occurred.
Event: contentStatusChanged
to ready
This event signifies that the content has been successfully processed and is ready for distribution.
Demo JSON:
{
"eventName": "contentStatusChanged",
"eventDetails": {
"contentId": "65ea2671a604d3b574ed632c",
"status": "ready",
"details": {
"contentType": "video",
"durationInSeconds": 61,
"maxResolution": "1080p",
"aspectRatio": "16:9",
"engageKit": {
"snapshots": [
"https://customer.c.mp2.fastevo.net/65ea2671a604d3b574ed632c/processed/video/content/snapshots/snapshot0-engage.webp",
"https://customer.c.mp2.fastevo.net/65ea2671a604d3b574ed632c/processed/video/content/snapshots/snapshot1-engage.webp",
"https://customer.c.mp2.fastevo.net/65ea2671a604d3b574ed632c/processed/video/content/snapshots/snapshot2-engage.webp"
],
"videoPreviews": [
"https://customer.c.mp2.fastevo.net/65ea2671a604d3b574ed632c/processed/video/content/videoPreview/preview-engage.mp4"
]
}
}
}
}
Event Details:
contentId
: The unique identifier of the content that has been processed and is ready.status
: The new status of the content. In this case, it'sready
, indicating that the content has been successfully processed and is available for use.details
: This field contains additional information about the processed content. The included fields depend on thecontentType
:durationInSeconds
: The total duration of the processed content, provided in seconds. This field is included for audio and video content.maxResolution
: The maximum resolution for the processed content if it is a video.contentType
: The type of content that has been processed. Possible values areimage
,video
, andaudio
.aspectRatio
: The aspect ratio of the content, provided as a string (e.g.,16:9
). This field is included for image and video content.engageKit
: This field is included for image and video content. It contains arrays ofsnapshots
andvideoPreviews
for video content, each with their respective access urls. Depending on your project configuration, direct access to the engage kit urls might be blocked, allowed for public or signing required (Access the documentation here).
This revised explanation should provide a more accurate and detailed understanding of the contentStatusChanged
to Ready
event and its associated details, including the different cases for when the contentType
is image
.
Event: contentStatusChanged
to deleting
This event indicates that the content is scheduled for deletion.
Demo JSON:
{
"eventName": "contentStatusChanged",
"eventDetails": {
"contentId": "65ea12190350c7c3ee9333da",
"status": "deleting"
}
}
Event Details:
contentId
: The unique identifier of the content that is scheduled for deletion.status
: The new status of the content. In this case, it'sdeleting
, indicating that the content is scheduled for deletion.
For each event type, the contentId
within eventDetails
is key to identifying the content in question. This consistent placement allows developers to easily extract and use the contentId
for further processing or tracking within their systems.