> ## 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: 3e6c7954-11a9-4667-b412-2cafb8d01211
---

# Webhook journal APIs

> Learn how to use the latest version of the webhook journal APIs (2026-03).

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

The journal API endpoints provide access to historical event data stored in chronological order, allowing you to query for changes that occurred for your subscriptions over the past 3 days. These endpoints are optimized for performant access to object and property change data, especially compared to alternatives like the [CRM search API](/api-reference/latest/crm/search-the-crm).

## Before you get started

You'll need to generate a client credentials token to use the webhook journals API. More information on how to generate this token is available in the authentication section of [overview](/api-reference/latest/webhooks-journal/guide#authentication-and-scopes) article.

## Retrieve journal data

The journal API has two variants:

* **Global journal** (`/webhooks-journal/journal/2026-03/...`): returns events across all accounts where the app is installed.
* **Local journal** (`/webhooks-journal/journal-local/2026-03/...`): returns events scoped to a specific account where the app is installed, identified by the optional `installPortalId` query parameter.

The sections below outline out how to retrieve the earliest, latest, or next entry in the journal.

* When using each of these endpoints, you'll need to ensure your [client credentials token](/api-reference/latest/webhooks-journal/guide#authentication-and-scopes) was generated with the `developer.webhooks_journal.read` scope specified.
* A successful response will include a `url` property, which you can then use to retrieve the file for the associated journal data.

### Get earliest journal entry

To retrieve the earliest available journal entry for your app, make 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"
}
```

### Get latest journal entry

To retrieve the latest available journal entry for your app, make a `GET` request to `/webhooks-journal/journal/2026-03/latest`.

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"
}
```

### Get next journal entry

To retrieve the next journal entry after a specific offset, make a `GET` request to `/webhooks-journal/journal/2026-03/offset/{offset}/next`. The `offset` path parameter is the UUID offset from the previous journal entry.

For example, using the response from the previous sections, you'd make a `GET` request to `/webhooks-journal/journal/2026-03/offset/550e8400-e29b-41d4-a716-446655440000/next`.

```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"
}
```

## Batch journal operations

Use batch operations for efficient retrieval of multiple journal entries in a single request, which improves throughput for high-volume data processing.

All batch endpoints are exempt from the standard daily and per-second API [rate limits](/developer-tooling/platform/usage-guidelines#rate-limits), but are still subject to the [journal-specific rate limits](#rate-limits) detailed at the bottom of this article.

When using each of the batch endpoints, you'll need to ensure your [client credentials token](/api-reference/latest/webhooks-journal/guide#authentication-and-scopes) was generated with the `developer.webhooks_journal.read` scope specified.

### Batch retrieve by offset

To retrieve multiple journal entries by offset UUID, make a `POST` request to `/webhooks/2026-03/journal/batch/read`. In the request body, provide the list of offset UUIDs within the `inputs` array.

The code block below provides an example JSON payload to include in your request body, along with an example `cURL` request to retrieve journal entries using three offset UUIDs:

<CodeGroup>
  ```json JSON theme={null}
    {
      "inputs": [
        "550e8400-e29b-41d4-a716-446655440000",
        "7c9e6679-7425-40de-944b-e07fc1f90ae7",
        "a3bb189e-8bf9-3888-9912-ace4e6543002"
      ]
    }
  ```

  ```bash cURL theme={null}
  curl -X POST \
    https://api.hubapi.com/webhooks-journal/journal/2026-03/batch/read \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "inputs": [
        "550e8400-e29b-41d4-a716-446655440000",
        "7c9e6679-7425-40de-944b-e07fc1f90ae7",
        "a3bb189e-8bf9-3888-9912-ace4e6543002"
      ]
    }'
  ```
</CodeGroup>

### Batch retrieve range of entries from an offset

To retrieve a set number of journal entries that follow a given offset, make a `GET` request to `/webhooks/2026-03/journal/batch/{offset}/next/{count}`.

Entries *after* the specified offset are returned in order, so the latest entry can be used as the offset for the next batch. You can also provide an optional `installPortalId` query parameter to filter results to a specific HubSpot account.

For example, to retrieve 10 entries after offset `550e8400-e29b-41d4-a716-446655440000`, you could make the following `cURL` request:

```bash theme={null}
curl -X GET \
  "https://api.hubapi.com/webhooks-journal/journal/2026-03/batch/550e8400-e29b-41d4-a716-446655440000/next/10" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

### Batch retrieve earliest entries

To retrieve the earliest entries in the journal for your app, make a `GET` request to `/webhooks-journal/journal/2026-03/batch/earliest/{count}`. This is useful for an initial backfill or replaying from the beginning of the journal. You can also provide an optional `installPortalId` query parameter to filter results to a specific HubSpot account.

For example, to retrieve the five earliest entries in the journal, you could make the following `cURL` request:

```bash theme={null}
curl -X GET \
  "https://api.hubapi.com/webhooks-journal/journal/2026-03/batch/earliest/5" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

### Batch retrieve latest entries

To retrieve the latest entries in the journal, make a `GET` request to `/webhooks-journal/journal/2026-03/batch/latest/{count}`. This can be useful for catching up after a gap in your data, or checking the most recent activity for your subscriptions. You can also provide an optional `installPortalId` query parameter to filter results to a specific HubSpot account.

For example, to retrieve the five most recent entries in the journal, you could make the following `cURL` request:

```bash theme={null}
curl -X GET \
  "https://api.hubapi.com/webhooks-journal/journal/2026-03/batch/latest/5" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

### Batch endpoint response format

All batch endpoints return the same response format that includes the following properties:

| Property      | Type   | Description                                                                  |
| ------------- | ------ | ---------------------------------------------------------------------------- |
| `status`      | String | The state of the request.                                                    |
| `startedAt`   | String | An ISO 8601 formatted timestamp denoting the time the request was initiated. |
| `completedAt` | String | An ISO 8601 formatted timestamp denoting the time the request was completed. |
| `results`     | Array  | A list of journal entries that match the parameters provided in the request. |
| `numErrors`   | Number | The number of errors that occurred while processing the request.             |
| `errors`      | Array  | A list of the detailed errors that occurred while processing the request.    |

The code block below provides an example successful response with a single journal entry returned:

```json theme={null}
{
  "status": "COMPLETE",
  "startedAt": "2024-01-01T12:00:00.000Z",
  "completedAt": "2024-01-01T12:00:00.123Z",
  "results": [
    {
      "url": "https://s3.amazonaws.com/bucket/path/to/journal.json",
      "expiresAt": "2024-01-01T13:00:00.000Z",
      "currentOffset": "550e8400-e29b-41d4-a716-446655440000"
    }
  ],
  "numErrors": 0,
  "errors": []
}
```

If one or more entries failed to be returned, they'll appear in the `errors` array. The failed offset UUID is located within `context.offset[0]` of each error element. An example internal error is shown below:

```json theme={null}
{
  "status": "error",
  "category": "INTERNAL_SERVER_ERROR",
  "message": "An internal error occurred while processing this journal entry. Please try again later.",
  "context": {
    "offset": ["a3bb189e-8bf9-3888-9912-ace4e6543002"]
  },
  "errors": [],
  "links": {}
}
```

Common error statuses you might encounter are detailed in the table below:

| Status             | Description                                                                                |
| ------------------ | ------------------------------------------------------------------------------------------ |
| `NOT_FOUND`        | No journal entry exists for the given offset.                                              |
| `PRESIGNING_ERROR` | The entry exists but a signed URL could not be generated. Retrying the offset may succeed. |
| `VALIDATION_ERROR` | Batch size exceeds the maximum allowed limit of 100 entries.                               |

### Get journal status

To retrieve the status of a journal snapshot operation, make a `GET` request to `/webhooks-journal/journal/2026-03/status/{statusId}`, where `statusId` is the UUID returned when a snapshot was requested.

### Local journal

The local journal endpoints follow the same pattern as the global journal, but are scoped to a specific account. Use the `installPortalId` query parameter to specify the account.

* `GET /webhooks-journal/journal-local/2026-03/earliest`
* `GET /webhooks-journal/journal-local/2026-03/latest`
* `GET /webhooks-journal/journal-local/2026-03/offset/{offset}/next`
* `GET /webhooks-journal/journal-local/2026-03/status/{statusId}`

## Rate limits

The journal API endpoints are subject to a limit of 100 requests per second per app.

Learn more about the related rate limits for the management APIs [here](/api-reference/latest/webhooks-journal/subscriptions/guide#rate-limits).
