> For the complete documentation index, see [llms.txt](https://docs.dapta.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dapta.ai/dapta-forms/connect/webhooks/payload-reference.md).

# Payload & headers reference

The exact JSON body and HTTP headers Dapta Forms sends to a webhook: form, submission, data and utm objects, the partial or complete phase, the x-forms-event, x-forms-delivery, x-forms-timestamp and X

Every webhook delivery is a `POST` with a JSON body in one stable shape. This page documents that shape field by field, the headers that travel with it, and what is different in a test delivery. You can see the exact body of any past delivery in the **Webhook history** dialog under **What we sent**.

<figure><img src="https://3835013762-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCy5rSNtQmtqYCGzJlNEB%2Fuploads%2Fgit-blob-e260f4de7af691111792532d7d7359a73e08804e%2Fforms-payload-reference-01-what-we-sent.png?alt=media" alt="The Webhook history dialog with one delivery expanded, showing the JSON under What we sent"><figcaption><p>Open any delivery in <strong>Webhook history</strong> to read the body that was sent.</p></figcaption></figure>

***

## Sample body

The shape below is real; the values are made up. Keys inside `data` are your own **Field key**s from the Build tab.

```json
{
  "id": "submission:6f1c0c2e-7d2a-4c9b-9e41-2f3a1b5c8d90:complete:webhook:0",
  "type": "form.submission",
  "phase": "complete",
  "submittedAt": "2026-08-22T02:13:04.790Z",
  "form": {
    "id": "19511bc5-a8e0-4445-b9b7-05bfffbb73a2",
    "name": "Lead qualification quiz"
  },
  "submission": {
    "id": "6f1c0c2e-7d2a-4c9b-9e41-2f3a1b5c8d90",
    "sessionId": "e19fd932-ee1f-4454-bf03-3418bdf54edb",
    "score": 12,
    "outcome": "Hot lead"
  },
  "data": {
    "email_1": "ada@example.com",
    "multiple_choice_2": "option_1",
    "firstname": "Ada",
    "lastname": "Lovelace",
    "utm": {
      "utm_source": "docs",
      "utm_medium": "guide",
      "utm_campaign": "webhooks"
    }
  },
  "utm": {
    "utm_source": "docs",
    "utm_medium": "guide",
    "utm_campaign": "webhooks"
  }
}
```

## Fields

| Field                  | Type           | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ---------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                   | string         | The idempotency key of this delivery, the same value as the `x-forms-delivery` header. Format `submission:{submissionId}:{phase}:webhook:{index}`. Store it and ignore a second request with the same `id`.                                                                                                                                                                                                                                                 |
| `type`                 | string         | Always `form.submission`.                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `phase`                | string         | `partial` when the respondent passed the partial submit point, `complete` when they finished. One session can produce both, in that order.                                                                                                                                                                                                                                                                                                                  |
| `submittedAt`          | string         | ISO-8601 timestamp (UTC) of this phase.                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `form.id`              | string         | The form's ID.                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `form.name`            | string         | The form's name at the time of sending.                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `submission.id`        | string         | The submission's ID. Identical for the partial and the complete delivery of the same session, which is how you link them.                                                                                                                                                                                                                                                                                                                                   |
| `submission.sessionId` | string         | The respondent's session.                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `submission.score`     | number         | Total score from the scoring settings, recomputed on the server. `0` when scoring is not used.                                                                                                                                                                                                                                                                                                                                                              |
| `submission.outcome`   | string or null | The heading of the outcome (score range) that matched, exactly as the respondent saw it. `null` when no range matches or scoring is off.                                                                                                                                                                                                                                                                                                                    |
| `data`                 | object         | One entry per answered question, keyed by **Field key** (for example `email_1`, `multiple_choice_2`). Single-choice and dropdown answers carry the option **Value**; multiple choice carries an array of values; sliders a number; a **Name** question arrives as `firstname` and `lastname`; a **File upload** arrives as an object, see below. Hidden fields are included. Unanswered questions are absent. `data.utm` holds the captured UTM parameters. |
| `utm`                  | object         | The UTM parameters captured from the public link (`utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content`), repeated at the top level for convenience. Empty object when the link had none.                                                                                                                                                                                                                                                   |

## File answers

A [File upload](/dapta-forms/builder/question-types/file-upload.md) answer is the one entry in `data` that is not a scalar. It arrives as an object:

```json
"file_1": {
  "name": "portfolio-cover.png",
  "size": "66398",
  "mime": "image/png",
  "key": "uploads/.../a4398e1d-....png"
}
```

| Field  | Meaning                                                                                                                          |
| ------ | -------------------------------------------------------------------------------------------------------------------------------- |
| `name` | The filename from the respondent's own computer. This is the one worth showing people.                                           |
| `size` | Size in bytes, as a string.                                                                                                      |
| `mime` | The content type the respondent's browser reported. It is never verified, so treat it as a hint and trust the extension instead. |
| `key`  | Where the file is stored. It is not a URL and it is not something you can fetch.                                                 |

The payload never carries the file itself and never carries a link to it. Links to uploaded files are created one click at a time and expire in minutes, which is exactly what a webhook payload must not contain. If your integration needs the file, fetch it from **Submissions** or have someone download it. See [Uploaded files](/dapta-forms/results/uploaded-files.md).

> **⚠️ Note:** Do not map a **File upload** question to a HubSpot property. HubSpot properties hold text, so a file answer does not arrive there as anything a person can read. Leave the question unmapped and open the file from **Submissions** instead.

## Headers

| Header              | Example                               | Meaning                                                                                                                                                                    |
| ------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `content-type`      | `application/json`                    | The body is always JSON.                                                                                                                                                   |
| `x-forms-event`     | `form.submission`                     | The event name, same as `type` in the body.                                                                                                                                |
| `x-forms-delivery`  | `submission:6f1c…:complete:webhook:0` | The idempotency key (same as `id` in the body). Unique per submission, phase and webhook. Retries of the same delivery reuse it.                                           |
| `x-forms-timestamp` | `1787364784`                          | Unix time in seconds when the delivery was created. Use it to reject stale requests if you want replay protection.                                                         |
| `X-Forms-Signature` | `sha256=b5b239…`                      | Present only when a **Signing secret** is set: `sha256=` + hex HMAC-SHA256 of the raw body. See [Verify the signature](/dapta-forms/connect/webhooks/verify-signature.md). |

Header names are case-insensitive; most frameworks expose them lowercase.

## Test deliveries

**Send test** posts the same envelope with sample answers so your endpoint sees the real shape. Differences from a real delivery:

* `id` and `x-forms-delivery` use the prefix `ping:` instead of `submission:`.
* `phase` is `partial`, `submission.id` is `test-submission` and `submission.sessionId` is `test-session`.
* `data` contains `"test": true` plus one sample answer per question: `sample@example.com` for Email, `+15555550123` for Phone, `https://example.com` for Website, `5` for Slider, `sample-option` for choice questions, `Sample` / `Respondent` for Name, `Sample answer` for everything else.
* `utm` is empty.

> **💡 Tip:** Treat `id` (or `x-forms-delivery`) as the primary key on your side. If your endpoint answers slowly and Dapta Forms retries, you will receive the same key again and can safely skip it.

## What's next

* [Verify the signature](/dapta-forms/connect/webhooks/verify-signature.md)
* [Test & delivery history](/dapta-forms/connect/webhooks/test-and-history.md)
* [Hidden fields & URL prefill](/dapta-forms/builder/hidden-fields-and-url-prefill.md): how hidden answers and UTMs get into `data`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.dapta.ai/dapta-forms/connect/webhooks/payload-reference.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
