> ## Documentation Index
> Fetch the complete documentation index at: https://80x.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook received

> The Webhook received trigger (external) starts a workflow when an external system sends JSON to the workflow's webhook URL.

The **Webhook received** trigger (external) starts a workflow when an external system sends JSON to the workflow's webhook URL. JSON is a plain-text format for structured data. Use this trigger as the entry point for any event that starts outside Attio, such as a product event, a form submission, or a partner lead. The data arrives untrusted, meaning you cannot assume it is well-formed or honest. For that reason, the first block after the trigger is almost always [Parse JSON](/reference/utilities/parse-json).

| | |
| - | - |
| **Category** | Trigger (external) |
| **Credit cost** | Free. Triggers consume no credits |
| **Engine** | New Workflows engine (June 2026+) |
| **Plan availability** | All plans |
| **Limits** | Requests must use `Content-Type: application/json`. Outputs are limited to the payload body and a timestamp; request headers are not exposed. |

## Inputs

The trigger generates a webhook URL when you add it to a workflow. You configure the external system, not the trigger itself. There are no fields to map.

| Input | Type | Required | Default | Notes |
| - | - | - | - | - |
| Webhook URL | URL (read-only) | n/a | Generated by Attio | Copy this URL into the sending system. The system must send an HTTP request with the header `Content-Type: application/json`. |

## Outputs

The trigger exposes two things: the raw request body and the time the request arrived. Request headers are not available as outputs. As a result, you cannot read authentication tokens or custom headers in later blocks.

| Output | Type | Example | Notes |
| - | - | - | - |
| Payload body | Text (raw JSON) | `{"email":"jane@acme.com","company":"acme.com"}` | The unparsed request body. Pass it to [Parse JSON](/reference/utilities/parse-json) before reading fields. |
| Timestamp | Datetime | `2026-06-11T14:32:05Z` | The moment Attio received the request. |

Reference the raw body in a later block as `{{ steps.webhook_received.body }}` and the arrival time as `{{ steps.webhook_received.timestamp }}`.

## Behavior

The trigger fires once for each incoming HTTP request that reaches the webhook URL. Attio passes the request body through as raw JSON text. It does not parse the payload, check that the fields are correct, or change a value from one type to another. Every field arrives exactly as the sender wrote it.

A request without the `Content-Type: application/json` header does not produce a usable run. Treat the payload as untrusted, which means you cannot assume the sender got it right. A sending system can leave out an optional field, send a number where you expected text, or change the shape of its data without warning. The body is raw text, so later blocks see no structure until you parse it.

## Gotchas

* **Fields read as empty until you parse the body.** The trigger output is raw JSON text, not structured data. A mapping such as `{{ steps.webhook_received.email }}` resolves to nothing. Follow the trigger with [Parse JSON](/reference/utilities/parse-json), then map fields from the parsed result.
* **The request silently does nothing without the JSON content type.** A sender that posts form-encoded data, or that omits the `Content-Type: application/json` header, will not produce a usable payload. Set the header on the sending system before testing.
* **A malformed or unexpected payload corrupts records downstream.** External systems change their schema without notice. A missing or wrong-typed field can write blank or incorrect values. Validate the parsed payload with a [Filter](/reference/conditions/filter) before any block that creates or updates a record.
* **Authentication headers are invisible to the workflow.** The trigger exposes only the body and a timestamp. You cannot verify a signature or bearer token from a request header. Carry any shared secret inside the JSON body and check it with a [Filter](/reference/conditions/filter).

## Examples

### Capturing a product signup

A product backend posts a signup event to the webhook URL whenever a new account is created.

```json theme={null}
{
  "email": "jane@acme.com",
  "full_name": "Priya Sharma",
  "company_domain": "acme.com",
  "plan": "pro"
}
```

Attio starts a run with this body available as `{{ steps.webhook_received.body }}`. From there, [Parse JSON](/reference/utilities/parse-json) exposes `email`, `full_name`, and `company_domain`.

### Routing a partner lead with a shared secret

A referral partner posts a lead and includes a shared secret in the body. The workflow uses that secret to confirm the source before writing anything.

```json theme={null}
{
  "secret": "hta-partner-2026",
  "email": "marcus.lee@northwind.io",
  "source": "northwind-referral"
}
```

After [Parse JSON](/reference/utilities/parse-json), add a [Filter](/reference/conditions/filter) that requires `secret` to equal `hta-partner-2026`. That filter blocks any request that lacks the value. Only verified leads reach the [Create or update record](/reference/records/create-or-update-record) block.

## Source

[Attio Workflows block library](https://attio.com/help/reference/automations/workflows/workflows-block-library).

Last reviewed against the Attio Help Center, June 2026.

## See also

* [Manual run](/reference/triggers/manual-run)
* [Recurring schedule](/reference/triggers/recurring-schedule)
* [Parse JSON](/reference/utilities/parse-json)
* [Choosing the right trigger](/explanation/triggers)
* [Webhook lead intake with safe upsert](/guides/capture-and-qualify/webhook-lead-intake)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.