publ betaReference (MCP guide)
Open publ console

terms_apply

[Migration map](../reference/tool-name-migration.md).

# terms_apply

Save, publish or reset language-specific drafts of an existing channel term. Start with a [key-specific get](publ_terms_get.md) for the same channel/key, and use the user's supplied content and publication intent. A save-and-publish sequence is not atomic.

| Common input | Contract |
| --- | --- |
| `requestId` | Required, 8–80 ASCII letters/digits/underscores/hyphens; keep it for the original task |
| `channelCode` | Required nonempty selected-channel code, excluding `.` and `..` |
| `key` | Required one of the four editable `CH_*` keys listed by get |
| `expectedRevision` | Required 64 lowercase hexadecimal characters from the selected-key get |
| `operation` | Required operation from the table below |
| `dryRun` | Optional boolean, default false |

| Operation | Additional inputs and behavior |
| --- | --- |
| `save_draft` | At least one of `kr`/`en`; save both resolved language values as a draft, preserving an omitted language except null English normalizes to empty string |
| `publish_draft` | Required `confirmation:"PUBLISH_TERM"`; publish the existing draft, with no content inputs |
| `save_and_publish` | At least one of `kr`/`en` and required `confirmation:"PUBLISH_TERM"`; save necessary draft changes, then publish |
| `reset_draft` | Required `languages`, one or two unique entries from `kr`/`en`; copy selected languages from the source-defined original into a draft |

Each supplied HTML string permits 0–50,000 characters. Empty is an intentional empty value; omission is preservation. This bound is not claimed equivalent to the source editor's visible-character count. Existing omitted text is not revalidated against the input length limit. Unknown fields and inputs belonging to another operation are rejected. Duplicate reset languages fail planning with `TERMS_DUPLICATE_LANGUAGE`. Confirmation is required even for a publication dry run; a literal confirmation does not independently establish user authorization.

Plan a one-language draft:

```json
{"requestId":"terms-draft-example-001","channelCode":"selected-channel-code","key":"CH_MARKETING_AGREEMENT","expectedRevision":"0000000000000000000000000000000000000000000000000000000000000000","operation":"save_draft","kr":"<p>Replace with user-approved Korean content.</p>","dryRun":true}
```

Plan publication of a selected existing draft:

```json
{"requestId":"terms-publish-example-001","channelCode":"selected-channel-code","key":"CH_MARKETING_AGREEMENT","expectedRevision":"0000000000000000000000000000000000000000000000000000000000000000","operation":"publish_draft","confirmation":"PUBLISH_TERM","dryRun":true}
```

Plan saving and publishing a supplied English replacement:

```json
{"requestId":"terms-composed-example-001","channelCode":"selected-channel-code","key":"CH_MARKETING_AGREEMENT","expectedRevision":"0000000000000000000000000000000000000000000000000000000000000000","operation":"save_and_publish","en":"<p>Replace with user-approved English content.</p>","confirmation":"PUBLISH_TERM","dryRun":true}
```

Plan reset of one language to its source-defined original:

```json
{"requestId":"terms-reset-example-001","channelCode":"selected-channel-code","key":"CH_MARKETING_AGREEMENT","expectedRevision":"0000000000000000000000000000000000000000000000000000000000000000","operation":"reset_draft","languages":["kr"],"dryRun":true}
```

The zero revision and content above are placeholders, not reusable editing tokens or legal clauses. Replace them from a fresh selected get and the user's instructions. Do not expose passwords/tokens or supply profile IDs. The bridge derives a verified numeric author ID for transport while retaining a canonical string in its task context.

The current term must exist, the chosen DRAFT-or-CURRENT must have editable channel contents and platform-integrated terms must be disabled. Shared publ terms, new term kinds, deletion and required/optional consent changes are unsupported. `TERMS_PLATFORM_INTEGRATED` returns `action_required` with no write and platform-screen guidance. `TERMS_NO_DRAFT` blocks publication without a draft.

A fresh dry run validates revision and eligibility, computes `steps` and returns `PLAN_READY`, channel, impact and `writesPerformed:false`, without creating a task. An existing matching task's dry run returns saved `steps`, `index` and task identity; it is not a fresh revision check. If a saved draft already equals both resolved language values, the draft POST is omitted. Matching CURRENT alone still requires creating a draft. A no-op save/reset may complete as `TERMS_DRAFT_SAVED` without a POST.

For real work, the journal tracks prepared/sent/done and the step index. Every prepared step rechecks the snapshot and recomputes remaining actions from the original input. The returned write ID must be recorded before readback can certify that step. A missing acknowledgement ID remains unknown even if text looks correct. The [guide](../guides/terms.md#recover-the-original-task) explains definite rejection, partial publication, no replay and historical completion.

Draft completion uses `TERMS_DRAFT_SAVED`; publication uses `TERMS_PUBLISHED`. Results include task identity/type, phase/index, updated term view and revision. Verification compares list/detail/history and preservation; `legalReview`, `memberConsent` and `memberNotification` remain false. Draft checks retain CURRENT/history and unrelated records. Publication requires the acknowledged CURRENT with draft content, no remaining draft, the previous CURRENT retained as history except its stage, and older history/unrelated records unchanged.

Publication changes member-facing terms but does not prove rendering, legally adequate text, re-consent or notifications. Failed publication can leave a saved draft; there is no automatic deletion or rollback. Use task status/resume with `taskType:"terms"` and the original task ID, then get for current observations.

## Saved plan replay

For an existing matching task, `dryRun` returns historical saved plan/progress,
with `historical:true`, `replayed:true` and false current verification. It performs
no fresh business-state or eligibility check, no business effect and no journal
change. Current console/action links are omitted. Follow `nextStep` for the same
target's current state; keep the original task ID for uncertain-outcome recovery.
Context and saved-input checks still apply. A new task follows normal fresh-plan
validation; another request ID must not bypass an uncertain effect.

`nextStep` uses terms_get with the original channelCode and key; saved phase, steps and index are retained, including a draft saved before publication failed.

## Saved record identity

Apply/dry-run replay and task status/resume bind both the saved ID and saved input
requestId to the requested task ID. An intact record stored under another lookup
key is also refused with `TASK_STATE_UNVERIFIED`, before business reads or effects.
Keep both records for inspection; do not rename/edit them, use the embedded ID or
create a replacement task to bypass refusal. Matching tasks keep their existing
validation and recovery rules. Connection/authorization checks may still run;
this guard is not a complete record schema or current-state verification.

## Inputs

| Field | Required here | Contract |
| --- | --- | --- |
| `key` | Yes | one of: `CH_TERMS_OF_SERVICE`, `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO`, `CH_MARKETING_AGREEMENT`, `CH_PRIVACY_POLICY`, `CH_TERMS_OF_SERVICE`, `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO`, `CH_MARKETING_AGREEMENT`, `CH_PRIVACY_POLICY`, `CH_TERMS_OF_SERVICE`, `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO`, `CH_MARKETING_AGREEMENT`, `CH_PRIVACY_POLICY`, `CH_TERMS_OF_SERVICE`, `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO`, `CH_MARKETING_AGREEMENT`, `CH_PRIVACY_POLICY` |
| `operation` | Yes | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: `save_draft` |
| `kr` | No | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: string; max length 50000 |
| `en` | No | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: string; max length 50000 |
| `confirmToken` | No | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: string; pattern `^ct[a-f\d]{32}$`; The confirmToken from this tool's preview result. Omit it to preview; repeat the same input with it to execute. |
| `operation` | Yes | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: `publish_draft` |
| `confirmToken` | No | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: string; pattern `^ct[a-f\d]{32}$`; The confirmToken from this tool's preview result. Omit it to preview; repeat the same input with it to execute. |
| `operation` | Yes | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: `reset_draft` |
| `languages` | No | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: array; items: `kr`, `en`; min items 1; max items 2; default `["kr","en"]` |
| `confirmToken` | No | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: string; pattern `^ct[a-f\d]{32}$`; The confirmToken from this tool's preview result. Omit it to preview; repeat the same input with it to execute. |
| `operation` | Yes | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: `save_and_publish` |
| `kr` | No | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: string; max length 50000 |
| `en` | No | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: string; max length 50000 |
| `confirmToken` | No | When `key` is `CH_TERMS_OF_SERVICE` or `CH_PRIVACY_POLICY_FOR_PERSONAL_INFO` or `CH_MARKETING_AGREEMENT` or `CH_PRIVACY_POLICY`: string; pattern `^ct[a-f\d]{32}$`; The confirmToken from this tool's preview result. Omit it to preview; repeat the same input with it to execute. |