[Migration map](../reference/tool-name-migration.md).
# channels_mark_apply — archive or unarchive channels
Change selected channels' classification in the connected account's directory. `NO_INTEREST` archives them and `RUNNING` unarchives them. This does not delete, deactivate, unpublish, relaunch, or cancel payment for a channel. Multiple targets are processed sequentially without automatic rollback.
Current response compatibility follows the [source channel-code fallback](../reference/README.md#current-channel-directory-alias-compatibility), including explicit null legacy fields. It does not change inputs, normalized revisions or task recovery.
## Input
| Field | Type | Required | Constraint |
| --- | --- | --- | --- |
| `requestId` | string | Yes | 8–80 ASCII letters, digits, underscores, or hyphens: `^[A-Za-z0-9_-]{8,80}$`. |
| `targets` | object array | Yes | 1–50 entries, with distinct channel codes and preserved request order. |
| `targets[].channelCode` | string | Yes | Nonempty, excluding `.` and `..`. |
| `targets[].expectedRevision` | string | Yes | Current lowercase 64-character hexadecimal revision from the channel list. |
| `markChannelAs` | enum string | Yes | `RUNNING` or `NO_INTEREST`, applied to every selected target. |
| `dryRun` | boolean | No | `false`. Use `true` to inspect a plan before writing. |
Both the top-level object and target objects reject additional fields. No field accepts `null`.
```json
{
"requestId": "example-channel-archive-001",
"targets": [{
"channelCode": "selected-channel-code",
"expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000"
}],
"markChannelAs": "NO_INTEREST",
"dryRun": true
}
```
The code and zero revision are placeholders, not executable current values. Replace them with one row's actual `channelCode` and `revision` from [channels_list](publ_channels_list.md). After inspecting the plan, keep the request ID and all business inputs identical and change only `dryRun` to `false`. The saved fingerprint includes target order and revisions. Changing them on an existing ID returns `TASK_CONTEXT_CHANGED`.
## Plan and execution
For a new request, the workflow reads both `RUNNING` and `NO_INTEREST` lists, without feature filtering, in pages of 100. It checks page completeness, stable per-list totals, unique IDs/codes across both lists, account membership, and a combined maximum of 5,000 rows. The selected rows must match their supplied revisions.
A new dry run returns `status:success`, `code:PLAN_READY`, `taskType:channel-archive`, `environment`, `impact`, `writesPerformed:false`, and `targets` containing `channelCode`, `title`, `from`, `to`, and `writeNeeded`. It does not create a job or return a `taskId`. A dry run for an existing job instead returns its `taskId` and saved `from`/`to` targets; it does not refresh the directory or supply the new-plan `title`/`writeNeeded` fields.
Real execution saves a job. Before each target it rereads both full lists and compares all selected rows with the expected checkpoint. A target already at the desired classification requires no POST and still counts as completed. Otherwise it sends one account-authenticated `POST /seller/api/v2/channels/{channelCode}/mark-channel-as` with `{markChannelAs}`, then rereads both lists. No per-channel credential or credential refresh is required for this account operation.
Readback checks the changed target and preservation of the other selected targets' directory fields. A final read verifies all selected rows. This is not a server-side atomic comparison/update, an account-wide preservation guarantee for unselected rows, or proof that no other actor wrote identical values.
## Completion result
| Field | Meaning |
| --- | --- |
| `status`, `code` | `success`, `CHANNEL_MARK_APPLIED`. |
| `taskId`, `taskType` | Original request ID and `channel-archive`. |
| `phase` | `done`. |
| `completedCount`, `targetCount` | Verified targets and total selected targets; completed count includes no-op targets, not only POSTs. |
| `channels` | Selected normalized directory rows in request order, with their new revisions; no `credentialPresent` field. |
| `environment`, `impact` | Adapter label and the classification-only/partial-batch limits. |
| `verification` | `confirmed:true`, `method:complete_account_lists`, `channelLifecycleChanged:false`. |
Non-demo new plans and fresh verified completions add the classification-specific parent `consoleUrl` described below. Earlier targets can remain changed when a later target fails. Read the saved progress and last result before deciding what to do next.
## Recovery
Use the original ID and `taskType:channel-archive` with [task_status](publ_task_status.md) or, when continuing the original operation, [task_resume](publ_task_resume.md). Status reports the phase, counts, and `lastResult`. Both operations require the original connection and state storage.
| Phase | Meaning and resume behavior |
| --- | --- |
| `prepared` | The current target has not been sent, or a definite rejection/not-sent failure restored this phase. Recheck the checkpoint before performing remaining writes. |
| `sent` | The workflow persisted this phase before POST. Observe current directory state; never resend this uncertain change. If the expected next checkpoint matches, advance to the next target; otherwise return `CHANNEL_MARK_OUTCOME_UNKNOWN`. |
| `done` | Return the historical stored completion. It is not a fresh directory read. |
A lost response does not justify a new request ID. Do not change the saved connection, targets, revisions, or job data to bypass a conflict. To intentionally undo a completed archive, read the current `NO_INTEREST` rows, obtain fresh revisions, and create a new authorized `RUNNING` operation. That is a separate change, not automatic rollback.
## Inputs
| Field | Required here | Contract |
| --- | --- | --- |
| `channels` | Yes | array; items: string; min length 1; max length 512; min items 1; max items 50; The channel codes from channels_list. |
| `markChannelAs` | Yes | `RUNNING`, `NO_INTEREST`; NO_INTEREST archives, RUNNING restores. |
| `confirmToken` | No | 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. |
## Failures and limits
| Code | Meaning and response |
| --- | --- |
| `CHANNEL_MARK_CONFLICT` | Initial revision or a selected-row checkpoint changed. Inspect current state and saved progress before replanning. |
| `CHANNEL_DIRECTORY_UNVERIFIED` | A list response or page is incomplete/malformed. It cannot establish absence or completion. |
| `CHANNEL_DIRECTORY_CHANGED` | List totals or uniqueness changed while reading. Stop and reassess the original task. |
| `CHANNEL_DIRECTORY_LIMIT` | More than 5,000 account rows cannot be processed by this workflow; use the console. |
| `CHANNEL_NOT_IN_ACCOUNT` | A target is absent from the fully read current account directory. |
| `CHANNEL_MARK_OUTCOME_UNKNOWN` | The sent change or preservation of selected peers cannot be verified. Inspect the original task; its uncertain POST will not be replayed. |
| `TASK_CONTEXT_CHANGED`, `CONNECTION_CHANGED` | Saved input/connection no longer matches. Do not move the task to a different account. |
Authentication, HTTP, private-storage, and locking failures can also occur. Outer failures can omit progress fields. In hosted mode both this tool and `channel-archive` recovery belong to the account resource, not a selected-channel resource.
Implementation: `src/channel-archive.ts`, `src/channel-directory.ts`, `src/publ-http.ts`, and the archive wrapper in `src/server.ts`.
## Saved plan replay
An existing task's `dryRun` returns historical saved plan/progress, with
`historical:true`, `replayed:true` and false current verification. It does not
freshly read the business state, repeat effects or change the journal, and it has
no current console link. Follow `nextStep` for a current observation; keep the
original task ID for uncertain-outcome status/resume. A new task still follows
normal fresh-plan validation. Do not create another ID to bypass uncertainty.
Saved phase, completedCount/targetCount and from/to targets remain available.
nextStep reads channels_list for the requested markChannelAs, without asserting
that the current directory already matches that classification.
## Archive-result destination
New plans and progress include the intended `markChannelAs`. A new `PLAN_READY`
and a freshly verified `CHANNEL_MARK_APPLIED` return one parent console link at
`/all-channels?page=1&limit=15&markChannelAs=<requested-classification>` through the
central console origin. A batch can span multiple pages, so this is its matching
classification's parent list, not a claim that every selected channel appears on
the first page. A plan has not saved the classification. Follow the current
directory pagination to find each selected identity after a completed operation.
Navigation validates the plan's target transitions or the completion's counts,
identities and classifications. Partial failures, uncertain outcomes and stored
history provide no current destination. Read progress and use the original task
for recovery; a missing link never permits resending an uncertain write. The
earlier saved-plan replay contract remains in force. No site launch, suspension,
publication, payment or deletion action follows from an archive classification.
## Saved record identity
Existing apply/dry-run calls and task status/resume require both the saved task ID
and saved input requestId to match the requested ID. A mismatching or malformed
saved identity returns `TASK_STATE_UNVERIFIED` before workflow context or business
reads. Preserve the original record for inspection; do not rename/edit it, try
its embedded ID or create a replacement request to bypass the error. No record
is repaired or resent. Matching records retain their existing recovery and
freshness checks; this rule does not convert them into universally read-only calls.