---
title: How to configure and use submission webhooks in Vloggi
description: "A Vloggi submission webhook sends an automatic notification to another system after Vloggi accepts a completed video submission. You can send the notification to an automation platform or to an HTTPS endpoint that you control. The `submission.received` event includes Vloggi's…"
url: "https://vloggi.com/docs/how-to-configure-and-use-submission-webhooks-in-vloggi/"
updated: "2026-08-12"
---

# How to configure and use submission webhooks in Vloggi

A Vloggi submission webhook sends an automatic notification to another system
after Vloggi accepts a completed video submission. You can send the notification
to an automation platform or to an HTTPS endpoint that you control.

The `submission.received` event includes Vloggi's unique submission ID, the
selected project, clip IDs, file count and submission time. When the contributor
arrived through a prefilled link, the event also includes the external reference
and any additional hand-off metadata.

This lets you confirm completion, update a survey or CRM record, trigger a
follow-up workflow, or build a reliable audit trail without asking the
contributor to enter the same identifier again.

To pass an existing record ID into Vloggi first, see [How to use prefilled upload links in Vloggi](https://vloggi.com/docs/how-to-use-prefilled-upload-links-in-vloggi/).

> A `submission.received` event confirms that Vloggi accepted the submission.
> Video encoding and other media processing may still be continuing.

## Before you start

You need:

- access to **Integrations** in Vloggi Studio;
- a Vloggi project to monitor; and
- a public HTTPS webhook URL from your automation platform or application.

The endpoint must use standard HTTPS without embedded credentials or a custom
port. For security, Vloggi will not deliver to localhost, private network
addresses or hosts that resolve to a private address, and it does not follow
redirects.

## Connect a webhook

1. Sign in to Vloggi Studio and open **Integrations**.
2. In **Submission webhooks**, select the project to monitor.
3. Paste the receiving system's public HTTPS webhook URL.
4. Leave **Enabled** selected.
5. Select **Connect webhook**.
6. Copy the signing secret immediately and store it securely.

The signing secret is shown only when the webhook is first connected or when
you deliberately rotate it. Vloggi does not display the existing secret again.

Webhook configuration is project-specific. Repeat these steps for each project
that needs its own endpoint.

## Using an automation platform

In your automation platform:

1. Create a workflow with a webhook or "catch hook" trigger.
2. Copy its HTTPS URL into Vloggi Studio.
3. Make a test Vloggi submission so the platform can inspect a sample payload.
4. Map `data.externalReference` to the originating record when you used a
   prefilled link. Otherwise, store `data.submissionId` as Vloggi's unique
   reference.
5. Add the actions that should run after completion.
6. Ensure the webhook trigger returns a `2xx` response promptly.

If the platform supports custom signature verification, validate the Vloggi
signature before running downstream actions. If it does not, use the platform's
recommended secure webhook URL controls and avoid exposing the URL.

## Webhook request

Vloggi sends an HTTPS `POST` with `Content-Type: application/json` and these
headers:

| Header | Purpose |
| --- | --- |
| `X-Vloggi-Event-Id` | Stable unique ID for this event. Use it as the idempotency key. |
| `X-Vloggi-Event-Type` | Currently `submission.received`. |
| `X-Vloggi-Timestamp` | Time the event was created, in ISO 8601 format. |
| `X-Vloggi-Signature` | HMAC-SHA256 signature in the form `sha256=<hex digest>`. |
| `User-Agent` | `Vloggi-Webhooks/1.0`. |

An example payload is:

```
{
  "id": "be1077ac-4a0c-4324-9f21-c3144ef89a53",
  "type": "submission.received",
  "createdAt": "2026-08-12T04:21:36.000Z",
  "data": {
    "submissionId": "41506315-6ff2-4f07-8f14-c2e102853e30",
    "externalReference": "RESP-80419",
    "handoffMetadata": {
      "study": "VIEWERS-2026",
      "panel": "uk-viewers"
    },
    "status": "received",
    "submittedAt": "2026-08-12T04:21:35.620Z",
    "fileCount": 2,
    "clipIds": [1293, 1294],
    "project": {
      "id": 68,
      "slug": "MBN-068",
      "name": "Viewer research"
    }
  }
}
```

`externalReference` is `null` and `handoffMetadata` is empty when the submission
did not receive those values from a prefilled link.

## Verify the signature

For an endpoint you control, calculate an HMAC-SHA256 digest over:

```
<X-Vloggi-Timestamp>.<raw request body>
```

Use the webhook signing secret as the HMAC key, prefix the resulting hexadecimal
digest with `sha256=`, and compare it with `X-Vloggi-Signature` using a
constant-time comparison.

The raw request body must be used exactly as received. Parsing and then
re-serialising the JSON can change whitespace or key order and invalidate the
signature.

Example using Node.js and Express:

```
import crypto from 'node:crypto'
import express from 'express'

const app = express()

app.post('/vloggi-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const timestamp = req.get('X-Vloggi-Timestamp') || ''
  const receivedSignature = req.get('X-Vloggi-Signature') || ''
  const rawBody = req.body.toString('utf8')

  const expectedSignature = `sha256=${crypto
    .createHmac('sha256', process.env.VLOGGI_WEBHOOK_SECRET)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex')}`

  const received = Buffer.from(receivedSignature)
  const expected = Buffer.from(expectedSignature)
  const valid = received.length === expected.length && crypto.timingSafeEqual(received, expected)

  if (!valid) return res.sendStatus(401)

  const event = JSON.parse(rawBody)
  // Ignore event.id if it has already been processed.
  // Queue your business processing, then acknowledge promptly.
  res.sendStatus(204)
})
```

Store the signing secret in a secrets manager or protected environment variable,
not in source code or browser-side JavaScript.

## Make your receiver idempotent

Network retries can deliver the same event more than once. Before applying an
update, check whether `X-Vloggi-Event-Id` or the payload's top-level `id` has
already been processed. If it has, return a successful `2xx` response without
repeating the action.

Retries retain the event's original ID and creation timestamp. Do not reject a
legitimate retry solely because its timestamp is older than a short freshness
window. Signature verification plus event-ID deduplication is the safer pattern.

## Response and retry behaviour

Your endpoint should return any `2xx` response within 10 seconds. Vloggi treats
non-`2xx` responses, timeouts, connection failures and redirects as failed
deliveries.

Vloggi makes up to five attempts:

1. immediately after the submission is accepted;
2. approximately 1 minute after the first failure;
3. approximately 5 minutes after the second failure;
4. approximately 30 minutes after the third failure; and
5. approximately 2 hours after the fourth failure.

After the fifth failure, the delivery is marked **failed**. You can inspect its
status and manually queue another attempt from **Recent deliveries** in Vloggi
Studio.

Respond quickly and move slow downstream work to your own queue. Do not make
Vloggi wait for lengthy CRM, media-processing or reporting operations.

## Monitor deliveries

The **Recent deliveries** table shows the most recent deliveries for the
selected project, including:

- Vloggi submission ID;
- delivery status;
- number of attempts;
- last HTTP response status; and
- a manual **Retry** action for undelivered events.

Use **Refresh** to retrieve the latest state.

## Rotate or disconnect the webhook

Select **Rotate signing secret** if a secret may have been exposed or when your
security policy requires rotation. Copy the new secret and update the receiving
system immediately; future deliveries are signed with the new secret.

Clear **Enabled** and save when you need to pause delivery without removing the
configuration. Select **Disconnect** when the project should no longer send
webhooks.

## Troubleshooting

**Vloggi rejects the webhook URL**
Use a public `https://` URL on the standard HTTPS port. Remove embedded
usernames, passwords and redirects. Localhost and private IP addresses cannot
receive production webhooks.

**The delivery times out**
Return a `2xx` response within 10 seconds and perform longer work asynchronously.

**Signature verification fails**
Use the raw request bytes, the exact `X-Vloggi-Timestamp` header and the current
signing secret. Confirm that no middleware parsed or changed the body first.

**The workflow runs twice**
Deduplicate using the event ID before applying changes.

**The external reference is null**
The contributor did not arrive with an `externalReference` parameter. Use a
prefilled upload link or match using Vloggi's `submissionId`.

**The video is not ready when the webhook arrives**
The webhook confirms submission acceptance, not completion of encoding. Use the
IDs in the event as references and allow media processing to continue.

## Recommended test checklist

- Use a test project and test receiving endpoint first.
- Save the signing secret securely.
- Submit with a unique test `externalReference`.
- Verify the HMAC signature using the raw body.
- Confirm that the external reference matches the originating record.
- Confirm that replaying the same event does not repeat the downstream action.
- Test a temporary failure and confirm the retry appears in Vloggi Studio.
- Rotate the secret and verify the receiver accepts only the new secret.

How to configure and use submission webhooks in Vloggi

A Vloggi submission webhook sends an automatic notification to another system
after Vloggi accepts a completed video submission. You can send the notification
to an automation platform or to an HTTPS endpoint that you control.

The `submission.received` event includes Vloggi's unique submission ID, the
selected project, clip IDs, file count and submission time. When the contributor
arrived through a prefilled link, the event also includes the external reference
and any additional hand-off metadata.

This lets you confirm completion, update a survey or CRM record, trigger a
follow-up workflow, or build a reliable audit trail without asking the
contributor to enter the same identifier again.

To pass an existing record ID into Vloggi first, see [How to use prefilled upload links in Vloggi](https://vloggi.com/docs/how-to-use-prefilled-upload-links-in-vloggi/).

> A `submission.received` event confirms that Vloggi accepted the submission.
> Video encoding and other media processing may still be continuing.

## Before you start

You need:

- access to **Integrations** in Vloggi Studio;
- a Vloggi project to monitor; and
- a public HTTPS webhook URL from your automation platform or application.

The endpoint must use standard HTTPS without embedded credentials or a custom
port. For security, Vloggi will not deliver to localhost, private network
addresses or hosts that resolve to a private address, and it does not follow
redirects.

## Connect a webhook

1. Sign in to Vloggi Studio and open **Integrations**.
2. In **Submission webhooks**, select the project to monitor.
3. Paste the receiving system's public HTTPS webhook URL.
4. Leave **Enabled** selected.
5. Select **Connect webhook**.
6. Copy the signing secret immediately and store it securely.

The signing secret is shown only when the webhook is first connected or when
you deliberately rotate it. Vloggi does not display the existing secret again.

Webhook configuration is project-specific. Repeat these steps for each project
that needs its own endpoint.

## Using an automation platform

In your automation platform:

1. Create a workflow with a webhook or "catch hook" trigger.
2. Copy its HTTPS URL into Vloggi Studio.
3. Make a test Vloggi submission so the platform can inspect a sample payload.
4. Map `data.externalReference` to the originating record when you used a
   prefilled link. Otherwise, store `data.submissionId` as Vloggi's unique
   reference.
5. Add the actions that should run after completion.
6. Ensure the webhook trigger returns a `2xx` response promptly.

If the platform supports custom signature verification, validate the Vloggi
signature before running downstream actions. If it does not, use the platform's
recommended secure webhook URL controls and avoid exposing the URL.

## Webhook request

Vloggi sends an HTTPS `POST` with `Content-Type: application/json` and these
headers:

| Header | Purpose |
| --- | --- |
| `X-Vloggi-Event-Id` | Stable unique ID for this event. Use it as the idempotency key. |
| `X-Vloggi-Event-Type` | Currently `submission.received`. |
| `X-Vloggi-Timestamp` | Time the event was created, in ISO 8601 format. |
| `X-Vloggi-Signature` | HMAC-SHA256 signature in the form `sha256=<hex digest>`. |
| `User-Agent` | `Vloggi-Webhooks/1.0`. |

An example payload is:

```
{
  "id": "be1077ac-4a0c-4324-9f21-c3144ef89a53",
  "type": "submission.received",
  "createdAt": "2026-08-12T04:21:36.000Z",
  "data": {
    "submissionId": "41506315-6ff2-4f07-8f14-c2e102853e30",
    "externalReference": "RESP-80419",
    "handoffMetadata": {
      "study": "VIEWERS-2026",
      "panel": "uk-viewers"
    },
    "status": "received",
    "submittedAt": "2026-08-12T04:21:35.620Z",
    "fileCount": 2,
    "clipIds": [1293, 1294],
    "project": {
      "id": 68,
      "slug": "MBN-068",
      "name": "Viewer research"
    }
  }
}
```

`externalReference` is `null` and `handoffMetadata` is empty when the submission
did not receive those values from a prefilled link.

## Verify the signature

For an endpoint you control, calculate an HMAC-SHA256 digest over:

```
<X-Vloggi-Timestamp>.<raw request body>
```

Use the webhook signing secret as the HMAC key, prefix the resulting hexadecimal
digest with `sha256=`, and compare it with `X-Vloggi-Signature` using a
constant-time comparison.

The raw request body must be used exactly as received. Parsing and then
re-serialising the JSON can change whitespace or key order and invalidate the
signature.

Example using Node.js and Express:

```
import crypto from 'node:crypto'
import express from 'express'

const app = express()

app.post('/vloggi-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const timestamp = req.get('X-Vloggi-Timestamp') || ''
  const receivedSignature = req.get('X-Vloggi-Signature') || ''
  const rawBody = req.body.toString('utf8')

  const expectedSignature = `sha256=${crypto
    .createHmac('sha256', process.env.VLOGGI_WEBHOOK_SECRET)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex')}`

  const received = Buffer.from(receivedSignature)
  const expected = Buffer.from(expectedSignature)
  const valid = received.length === expected.length && crypto.timingSafeEqual(received, expected)

  if (!valid) return res.sendStatus(401)

  const event = JSON.parse(rawBody)
  // Ignore event.id if it has already been processed.
  // Queue your business processing, then acknowledge promptly.
  res.sendStatus(204)
})
```

Store the signing secret in a secrets manager or protected environment variable,
not in source code or browser-side JavaScript.

## Make your receiver idempotent

Network retries can deliver the same event more than once. Before applying an
update, check whether `X-Vloggi-Event-Id` or the payload's top-level `id` has
already been processed. If it has, return a successful `2xx` response without
repeating the action.

Retries retain the event's original ID and creation timestamp. Do not reject a
legitimate retry solely because its timestamp is older than a short freshness
window. Signature verification plus event-ID deduplication is the safer pattern.

## Response and retry behaviour

Your endpoint should return any `2xx` response within 10 seconds. Vloggi treats
non-`2xx` responses, timeouts, connection failures and redirects as failed
deliveries.

Vloggi makes up to five attempts:

1. immediately after the submission is accepted;
2. approximately 1 minute after the first failure;
3. approximately 5 minutes after the second failure;
4. approximately 30 minutes after the third failure; and
5. approximately 2 hours after the fourth failure.

After the fifth failure, the delivery is marked **failed**. You can inspect its
status and manually queue another attempt from **Recent deliveries** in Vloggi
Studio.

Respond quickly and move slow downstream work to your own queue. Do not make
Vloggi wait for lengthy CRM, media-processing or reporting operations.

## Monitor deliveries

The **Recent deliveries** table shows the most recent deliveries for the
selected project, including:

- Vloggi submission ID;
- delivery status;
- number of attempts;
- last HTTP response status; and
- a manual **Retry** action for undelivered events.

Use **Refresh** to retrieve the latest state.

## Rotate or disconnect the webhook

Select **Rotate signing secret** if a secret may have been exposed or when your
security policy requires rotation. Copy the new secret and update the receiving
system immediately; future deliveries are signed with the new secret.

Clear **Enabled** and save when you need to pause delivery without removing the
configuration. Select **Disconnect** when the project should no longer send
webhooks.

## Troubleshooting

**Vloggi rejects the webhook URL**
Use a public `https://` URL on the standard HTTPS port. Remove embedded
usernames, passwords and redirects. Localhost and private IP addresses cannot
receive production webhooks.

**The delivery times out**
Return a `2xx` response within 10 seconds and perform longer work asynchronously.

**Signature verification fails**
Use the raw request bytes, the exact `X-Vloggi-Timestamp` header and the current
signing secret. Confirm that no middleware parsed or changed the body first.

**The workflow runs twice**
Deduplicate using the event ID before applying changes.

**The external reference is null**
The contributor did not arrive with an `externalReference` parameter. Use a
prefilled upload link or match using Vloggi's `submissionId`.

**The video is not ready when the webhook arrives**
The webhook confirms submission acceptance, not completion of encoding. Use the
IDs in the event as references and allow media processing to continue.

## Recommended test checklist

- Use a test project and test receiving endpoint first.
- Save the signing secret securely.
- Submit with a unique test `externalReference`.
- Verify the HMAC signature using the raw body.
- Confirm that the external reference matches the originating record.
- Confirm that replaying the same event does not repeat the downstream action.
- Test a temporary failure and confirm the retry appears in Vloggi Studio.
- Rotate the secret and verify the receiver accepts only the new secret.
