---
title: "Payloads"
description: "The webhook envelope, JSON encoding, realistic sample payloads, and the deleted-event rule."
canonical_url: https://developer.onepagecrm.com/webhooks/payloads/
source: Markdown mirror of https://developer.onepagecrm.com/webhooks/payloads/
---

Every webhook is a `POST` with exactly five top-level keys. No more,
no less.

## The envelope

| Key | Type | Description |
| --- | --- | --- |
| `type` | string | The entity that changed: `contact`, `company`, `deal`, `action`, `note`, `call`, `meeting` |
| `reason` | string | What happened: `created`, `updated`, `deleted`, `changed_to_won`, ... — see [Events](/webhooks/events/) |
| `timestamp` | integer | Unix time in seconds |
| `secretkey` | string | The secret you configured, or empty if the in-app form left it blank |
| `data` | object | The changed resource, nested under its entity key |

`data` is the resource serialized exactly like the API v3 response
for that resource — the same nested shape you get from
`GET /api/v3/contacts/{id}.json`, `GET /api/v3/deals/{id}.json`, and
so on. If you already parse API responses, you already parse webhook
payloads.

> **`data` is nested.** The resource sits under its entity key:
> `data.contact.first_name`, not `data.first_name`. The record's id
> is `data.contact.id`, `data.deal.id`, and so on — matching the
> `type` field. Contact events also carry sibling keys
> (`next_actions`, `next_action`, `queued_actions`,
> `most_urgent_action`) alongside `data.contact`, just like the API.
> The one exception is [deleted events](#deleted-events), where
> `data` is flat: `{ "id": "..." }`.

## Encoding

Webhooks are delivered as JSON. `Content-Type: application/json`, and
the body is the envelope as a JSON object:

```json
{
  "type": "note",
  "reason": "created",
  "timestamp": 1781426730,
  "secretkey": "your-configured-secret",
  "data": {
    "note": {
      "id": "5afc1b69d556730b580596cb",
      "author": "Jane D.",
      "contact_id": "5ae06ef9d55673108fe8877f",
      "text": "Met Jane at the Eco Conference. Wants a quote for 40 panels.",
      "date": "2026-06-10",
      "linked_deal_id": "",
      "linked_deal_name": "",
      "attachments": [],
      "created_at": "2026-06-10T08:46:10Z",
      "modified_at": "2026-06-10T08:46:10Z"
    }
  }
}
```

## Sample payloads

The samples below are built from the current API v3 schemas and
abridged for readability (`"...": "..."` marks omitted fields). The
authoritative field list for each resource is the
[API reference](/api/reference/).

### `contact`

The contact sits under `data.contact`, with its actions as sibling
keys — the same shape as `GET /api/v3/contacts/{id}.json`:

```json
{
  "type": "contact",
  "reason": "updated",
  "timestamp": 1781426730,
  "secretkey": "your-configured-secret",
  "data": {
    "contact": {
      "id": "5aba31ea9007ba0f570c92d4",
      "title": "Ms",
      "first_name": "Jane",
      "last_name": "Doe",
      "job_title": "Operations Lead",
      "starred": false,
      "company_id": "5aba31ea9007ba0f570c92d5",
      "company_name": "Acme Solar",
      "emails": [{ "type": "work", "value": "jane.doe@acmesolar.example" }],
      "phones": [{ "type": "work", "value": "(912) 644-1770" }],
      "urls": [{ "type": "website", "value": "https://acmesolar.example" }],
      "address_list": [],
      "status_id": "5e31e030849d781e837b6ba1",
      "status": "Prospect",
      "lead_source_id": "email_web",
      "lead_source": "Email or Web",
      "background": "",
      "owner_id": "5aba31e99007ba0f570c92a5",
      "tags": ["solar", "q3-pipeline"],
      "custom_fields": [],
      "created_at": "2026-05-12T09:14:02Z",
      "modified_at": "2026-06-10T08:45:30Z"
    },
    "next_actions": [
      {
        "id": "5aeac8789007ba56ffca92b9",
        "assignee_id": "5aaa9b009007ba08c9ebaef7",
        "contact_id": "5aba31ea9007ba0f570c92d4",
        "text": "Email Jane the revised quote",
        "status": "date",
        "date": "2026-06-12",
        "done": false,
        "...": "..."
      }
    ],
    "next_action": { "...": "..." },
    "queued_actions": [],
    "most_urgent_action": { "...": "..." }
  }
}
```

### `deal`

A status change uses the dynamic `changed_to_<status>` reason — see
[Events](/webhooks/events/#dynamic-deal-status-events):

```json
{
  "type": "deal",
  "reason": "changed_to_won",
  "timestamp": 1781426741,
  "secretkey": "your-configured-secret",
  "data": {
    "deal": {
      "id": "5aaa9b059007ba08c9ebaf58",
      "contact_id": "5aba31ea9007ba0f570c92d4",
      "owner_id": "5aba31e99007ba0f570c12f7",
      "name": "Solar panels — 40 units",
      "text": "Signed PO received.",
      "status": "won",
      "last_stage": 75,
      "close_date": "2026-06-10",
      "amount": 4500.0,
      "months": 1,
      "total_amount": 4500.0,
      "cost": 0.0,
      "date": "2026-05-20",
      "author": "Jane D.",
      "contact_info": {
        "contact_name": "Jane Doe",
        "company": "Acme Solar",
        "...": "..."
      },
      "created_at": "2026-05-20T16:10:45Z",
      "modified_at": "2026-06-10T08:45:41Z",
      "...": "..."
    }
  }
}
```

The stage and date keys depend on the deal's status:

- **Pending** deals carry `stage` and `expected_close_date`.
- **Won and lost** deals carry `last_stage` (the stage the deal
  closed from) and `close_date` instead.

### `action`

Completed actions serialize with `status: "done"`, `done: true`,
and a `done_at` date. There is no `date` key on a completed action:

```json
{
  "type": "action",
  "reason": "completed",
  "timestamp": 1781426755,
  "secretkey": "your-configured-secret",
  "data": {
    "action": {
      "id": "5aeac8789007ba56ffca92b9",
      "assignee_id": "5aaa9b009007ba08c9ebaef7",
      "contact_id": "5aba31ea9007ba0f570c92d4",
      "text": "Email Jane the revised quote",
      "status": "done",
      "done": true,
      "done_at": "2026-06-10",
      "created_at": "2026-06-09T11:52:09Z",
      "modified_at": "2026-06-10T08:45:55Z"
    }
  }
}
```

### `note`

```json
{
  "type": "note",
  "reason": "created",
  "timestamp": 1781426770,
  "secretkey": "your-configured-secret",
  "data": {
    "note": {
      "id": "5afc1b69d556730b580596cb",
      "author": "Jane D.",
      "contact_id": "5aba31ea9007ba0f570c92d4",
      "text": "Met Jane at the Eco Conference. Wants a quote for 40 panels.",
      "date": "2026-06-10",
      "linked_deal_id": "",
      "linked_deal_name": "",
      "attachments": [],
      "created_at": "2026-06-10T08:46:10Z",
      "modified_at": "2026-06-10T08:46:10Z"
    }
  }
}
```

When no deal is linked, `linked_deal_id` is `""` — an empty string,
never `null`.

`call`, `meeting`, and `company` events nest the same way:
`data.call`, `data.meeting`, `data.company`.

## Deleted events

When `reason` is `deleted`, `data` contains **only the `id`**, flat —
no entity key:

```json
{
  "type": "contact",
  "reason": "deleted",
  "timestamp": 1781426790,
  "secretkey": "your-configured-secret",
  "data": {
    "id": "5aba31ea9007ba0f570c92d4"
  }
}
```

This is always the case — it doesn't matter whether the delete is
still undoable. If you need the record's last state, keep your
own copy keyed by `id`, or treat the delete as a tombstone.

## Next

- [Delivery](/webhooks/delivery/) — when payloads arrive and what
  happens when delivery fails.
- [Security](/webhooks/security/) — verifying `secretkey` correctly.
