---
title: "Extension"
description: "Content Protection options, storage and editor events."
canonical_url: "https://tiptap.dev/docs/composable-docs/content-protection/api-reference/extension"
---

# Extension

Content Protection options, storage and editor events.

## `ContentProtection`

Checks document edits against a policy and replaces redacted content with placeholders. The extension adds no Nodes, Marks or attributes to the schema.

```ts
import { ContentProtection } from '@tiptap-pro/extension-content-protection'

ContentProtection.configure({ policy })
```

### Options (`ContentProtectionOptions`)

- `policy` (`ContentProtectionPolicy`): The active [policy](https://tiptap.dev/docs/composable-docs/content-protection/api-reference/policy.md). Default: `{ version: 1, rules: [] }`, allowing all reads and edits.
- `redactionText` (`string`): Default placeholder text, accessible name and clipboard text. Default: `'[Hidden content]'`. Must be nonempty.
- `renderRedaction` (`RedactionRenderer | null`): Creates the UI that replaces content hidden by a `read: false` policy. Receives safe placeholder props, including the text and accessible label from `redactionText`, and returns a DOM element with optional lifecycle callbacks. Use it for custom labels or host-owned controls such as a request-access button; it receives no hidden content and cannot grant access. Default: `null`, using the built-in placeholder. See [Redacted content](https://tiptap.dev/docs/composable-docs/content-protection/api-reference/rendering.md).
- `onRejected` (`(event: ContentProtectionRejectedEvent) => void`): Called after a policy refuses a document edit. The edit is not applied; use `event.violations` to show the user why, for example in a notification. This is the option form of the `contentProtectionRejected` event, not a callback that decides whether to allow the edit. Default: no-op, so refused edits show no application notification.
- `onPolicyUpdate` (`(event: ContentProtectionPolicyUpdateEvent) => void`): Listener for `contentProtectionPolicyUpdate`. Default: no-op.
- `onPolicyError` (`(event: ContentProtectionPolicyErrorEvent) => void`): Listener for `contentProtectionPolicyError`. Default: no-op.

Invalid initial options throw [`ProtectionConfigurationError`](https://tiptap.dev/docs/composable-docs/content-protection/api-reference/types.md#protectionconfigurationerror).

### Storage (`ContentProtectionStorage`)

Available at `editor.storage.contentProtection`.

- `policy` (`ContentProtectionPolicy`, readonly): The active policy.
- `policyRevision` (`number`, readonly): Starts at `0`; increments when the policy changes.
- `documentRevision` (`number`, readonly): Starts at `0`; increments for each applied content-changing transaction.

### `storage.checkTransaction`

Checks a proposed transaction without applying it. Equivalent to [`checkProtectedTransaction`](https://tiptap.dev/docs/composable-docs/content-protection/api-reference/utilities.md#checkprotectedtransaction).

#### Parameters

- `transaction` (`Transaction`): A transaction created from the editor's current state, passed as `{ transaction }`.

#### Returns (`ProtectionCheck`)

The permission result, violations and current revisions. Throws `ProtectionInputError` if the transaction's starting document does not match.

### `storage.isReadable`

Checks whether the entire range is readable under the active policy.

Accepts one options object: `{ document, range }`.

#### Parameters

- `document` (`Node`): The document to inspect.
- `range` (`{ from: number; to: number }`): The document range to check.

#### Returns (`boolean`)

`true` if the whole range is readable; otherwise `false`.

### Editor events

Register with `editor.on(name, listener)` and remove with `editor.off(name, listener)`. Option callbacks receive the same payloads.

| Event                           | Payload                              | Emitted when                           |
| ------------------------------- | ------------------------------------ | -------------------------------------- |
| `contentProtectionRejected`     | `ContentProtectionRejectedEvent`     | A transaction is refused.              |
| `contentProtectionPolicyUpdate` | `ContentProtectionPolicyUpdateEvent` | A different valid policy is installed. |
| `contentProtectionPolicyError`  | `ContentProtectionPolicyErrorEvent`  | A policy replacement is invalid.       |

See [event payloads](https://tiptap.dev/docs/composable-docs/content-protection/api-reference/types.md#contentprotectionrejectedevent). Dry-run checks emit no events; `renderRedaction` is a factory, not an event listener.
