> ## Documentation Index
> Fetch the complete documentation index at: https://developers.hubspot.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

---
id: 0b34ec9e-e3dc-4cdf-aa7e-a48a1de3e220
---

# Webhooks journal and management APIs (2026-03)

> Learn how to get started with the latest webhook journal and management APIs (2026-03)

export const RequiredIndicator = () => {
  return <span className="required-indicator">
      required
    </span>;
};

The webhooks journal API enables third-party integrators to subscribe to real-time events and retrieve historical event data. The subscription management API allows you to create and manage the subscriptions that drive which events appear in the journal.

<Warning>
  **Please note:** these APIs are managed by API only because they are install-specific, and don't work with the feature component functionality described in [this article](/apps/developer-platform/add-features/configure-webhooks).
</Warning>

## Authentication and scopes

All API endpoints require OAuth 2.0 authentication. The webhooks journal API uses a client credentials token to authorize actions on behalf of your app. Instructions for setting up this token can be found in the [authentication overview](/apps/developer-platform/build-apps/authentication/overview#client-credentials).

Based on the webhook management and journal endpoints you plan on using, include the corresponding `scopes` when generating your client credentials token:

* `developer.webhooks_journal.read`: access journal data.
* `developer.webhooks_journal.subscriptions.read`: retrieve subscription information.
* `developer.webhooks_journal.subscriptions.write`: create, update, and delete subscriptions.
* `developer.webhooks_journal.snapshots.read`: retrieve snapshot information.
* `developer.webhooks_journal.snapshots.write`: create and manage object snapshots.

In addition to the management scopes above, you'll also need to authorize any [scopes](/apps/developer-platform/build-apps/authentication/scopes) that correspond to the object types you're planning on subscribing to. For example, if you plan on subscribing to contact change events, you'll need to authorize the `crm.objects.contacts.read` scope.

For example, to generate a client credentials token with all available webhook journal and management permissions, you'd make the following API call:

```shell theme={null}
curl --location 'https://api.hubapi.com/oauth/2026-03/token' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'client_id=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
  --data-urlencode 'client_secret=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
  --data-urlencode 'scope=developer.webhooks_journal.read developer.webhooks_journal.subscriptions.read developer.webhooks_journal.subscriptions.write developer.webhooks_journal.snapshots.read developer.webhooks_journal.snapshots.write'
```

A successful request to the `https://api.hubapi.com/oauth/2026-03/token` endpoint will then return an access token you can include in the `Authorization` header of your requests:

```http theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```

You'll use this access token to make requests to both the journal API and management API endpoints.

## How to use the management and journal APIs

The management, journal, and snapshot APIs are designed to be used together:

* Use the management API endpoints to subscribe to specific events, or filter event data.
* After you've subscribed to specific events, you can use the journal API endpoints to access historical event data in chronological order. This allows you to query for subscription-related changes for the past three days. These endpoints are optimized for a performant response when checking object changes, especially compared to the alternative of using the [CRM search API](/api-reference/latest/crm/search-the-crm).
* Use the snapshots API endpoints to create snapshots of CRM objects at specific points in time.

Get started by checking out the individual API guides:

* [Webhook management API guide](/api-reference/latest/webhooks-journal/subscriptions/guide)
* [Webhook journal API guide](/api-reference/latest/webhooks-journal/journal-entries/guide)
* [Webhook snapshots API guide](/api-reference/latest/webhooks-journal/snapshots/guide)

## Event data format

After you've [created](/api-reference/latest/webhooks-journal/subscriptions/guide#create-or-update-a-subscription) your webhook subscriptions, you can [retrieve journal entries](/api-reference/latest/webhooks-journal/journal-entries/guide#retrieve-journal-data) using the journal API endpoints.

For example, when making a `GET` request to `/webhooks-journal/journal/2026-03/earliest`, the response will resemble the following:

```json theme={null}
{
  "url": "https://s3.amazonaws.com/bucket/path/to/journal/file.json",
  "expiresAt": "2024-01-01T12:00:00Z",
  "currentOffset": "550e8400-e29b-41d4-a716-446655440000"
}
```

When you retrieve the journal file using the `url` property in the response from these journal retrieval endpoints, the associated file contain JSON events in the following format:

### Contact creation event example

```json theme={null}
{
  "offset": "0197f5c0-4d9b-7932-83ec-06d56430c359",
  "journalEvents": [
    {
      "type": "crmObject",
      "portalId": 123456,
      "occurredAt": "2025-07-10T19:11:49.524Z",
      "action": "CREATE",
      "objectTypeId": "0-1",
      "objectId": 125119015226
    }
  ],
  "publishedAt": "2025-07-10T19:11:50.172Z"
}
```

### Contact update event example

```json theme={null}
{
  "offset": "0198197a-f0ac-7906-8bfe-a569398704ac",
  "journalEvents": [
    {
      "type": "crmObject",
      "portalId": 145534986,
      "occurredAt": "2025-07-17T17:42:23.540Z",
      "action": "UPDATE",
      "objectTypeId": "0-1",
      "objectId": 11073740016,
      "propertyChanges": {
        "lastname": "smith"
      }
    }
  ],
  "publishedAt": "2025-07-17T17:42:24.173Z"
}
```

### Association added example

```json theme={null}
{
  "offset": "0198199f-f454-7ee4-9766-779433c4864d",
  "journalEvents": [
    {
      "type": "association",
      "portalId": 145534986,
      "occurredAt": "2025-07-17T18:22:49.134Z",
      "action": "ASSOCIATION_ADDED",
      "fromObjectId": 11073740013,
      "toObjectId": 11073740016,
      "fromObjectTypeId": "2-134027637",
      "toObjectTypeId": "2-134027637",
      "associationTypeId": 17,
      "associationCategory": "USER_DEFINED",
      "isPrimary": false
    }
  ]
}
```

### App install and uninstall event journal payloads

If you [subscribe to app install and uninstall events](#create-an-app-install-or-uninstall-event-subscription), the corresponding journal events will resemble the following:

```json theme={null}
{
  "offset": "01983883-ee94-71df-8c20-9f3cbf039015",
  "journalEvents": [
    {
      "type": "app_lifecycle_event",
      "occurredAt": "2025-07-23T18:20:23.719Z",
      "action": "APP_INSTALL",
      "portalId": 123456,
      "eventTypeId": "4-1909196",
      "properties": {
        "hs_app_id": 1234567,
        "hs_app_install_level": "PORTAL",
        "hs_initiating_user_id": 987654321,
        "hs_user_id": 12345
      }
    }
  ],
  "publishedAt": "2025-07-23T18:20:27.196Z"
}
```

Note that the following event type IDs (`eventTypeId`) are available based on the triggered event:

* `4-1909196`: App install event
* `4-1916193`: App uninstall event

## Error handling

The API uses standard HTTP status codes to indicate success or failure:

### Success codes

* `200 OK`: request successful
* `204 No Content`: request successful with no response body

### Error codes

* `400 Bad Request`: invalid request parameters
* `401 Unauthorized`: missing or invalid authentication token
* `403 Forbidden`: insufficient permissions for the requested operation
* `404 Not Found`: requested resource not found
* `429 Too Many Requests`: rate limit exceeded
* `500 Internal Server Error`: server error

### Error response format

Error responses include details in the following format:

```json theme={null}
{
  "status": "error",
  "message": "Invalid subscription type provided",
  "correlationId": "550e8400-e29b-41d4-a716-446655440000",
  "category": "VALIDATION_ERROR"
}
```

## Rate limits

The following rate limits apply to the webhooks journal and subscription management APIs:

* **Journal API:** 100 requests per second per app
* **Subscriptions API:** 50 requests per second per app
* **Snapshots API:** 10 requests per second per app

When you exceed rate limits, you'll receive a `429 Too Many Requests` response with a `Retry-After` header indicating when you can retry.

<Warning>
  **Please note:** the limits above are subject to change. These rate limits are distinct from the rest of HubSpot's rate limits outlined [here](/developer-tooling/platform/usage-guidelines).
</Warning>

## Best practices

Keep the following best practices in mind when using the webhooks journal API:

### Journal processing

* **Sequential processing:** process journal files in chronological order using the offset system.
* **Offset management:** always store and use the `currentOffset` from responses for pagination.
* **URL expiration:** journal URLs expire after a set time — download files promptly.
* **Error handling:** implement exponential backoff for transient errors.

### Subscription management

* **Specific filters:** use object type and action filters to reduce unnecessary events.
* **Property selection:** only subscribe to properties you need to minimize data transfer.
* **Regular cleanup:** remove unused subscriptions to maintain performance.

### Snapshot usage

* **Batch requests:** group multiple snapshot requests into single API calls.
* **Property optimization:** only request properties you need for each object.
* **Timing considerations:** snapshots reflect object state at request time.
