Existing Channel Point charge products
# Existing Channel Point charge products
`channel_point_product_apply` composes the source WEB product editor and bulk visibility controls. It does not create products, change existing base prices, delete products, run onboarding, purchase points or move money. Bridge implementation: Original console source:
Read `channel_points_get` with `view:{kind:"products",page:1,limit:15}` first.
The reader repeats the exact page and current branding; a valid page returns
`productsRevision`. An out-of-range page retains its documented parent-link
fallback but has no write revision. Use the same page/limit in `sourcePage`.
Every selected `publProductId` must occur on that page. Numeric row IDs are not
product keys. OWNER or MANAGE_MONETIZATION permission is required.
For `action.kind:"edit"`, supply the selected `publProductId` and either or both:
- `representationalName`: trimmed source display name,4–20 UTF-16 code units.
- `bonusPoints`: nonnegative whole **displayed** bonus quantity. The observed
top-level branding ratio converts it to raw CP using exact decimal arithmetic.
Values requiring rounding or outside the exact supported range are rejected.
The resulting bonus cannot exceed the stored base charge quantity.
Omitted fields retain their stored values. The source request contains only
`representationalName` and `additionalChannelPointAmount`. Existing price strings,
currency, base quantity, product identities, type and activation are preserved.
The server's generated name, total amount and updated timestamp are observed;
the bridge does not invent a total-amount formula. Page/detail disagreement blocks
an edit. Original money strings are neither reformatted nor submitted.
For `action.kind:"visibility"`, supply unique `publProductIds` from the page and
`active:true` to show or`false` to hide them. The source request contains only
those IDs and uses bulk-activate/deactivate. A selected source-forced visible
product blocks the complete hide request. The result must independently show
the requested `isDeactivated` value for every selection; the server's separate
visibility summary is observed rather than inferred. Prices, point quantities
and all unselected page rows must remain unchanged. Partial batches stay pending.
Supply a stable `requestId`, `expectedRevision:productsRevision` and optional
`dryRun:true`. A dry run does not save or create a task. Unchanged values skip the
POST. Dispatch is journaled before the single source request. Edit accepts the
source200 data envelope; visibility accepts200/204. Neither response is enough
to claim completion: stable full-page readback, selected edit detail and preserved
branding/context are required. No server atomic lock or atomic batch is claimed.
After uncertainty, keep the original requestId and use `task_status`/`task_resume`
with `taskType:"point-products"`. Resume reads only and never resends the effect.
An untouched prepared task needs the identical apply input. Completed history
and existing-task dry runs are not current verification. Restoration needs a fresh
read and a new requestId after the preceding outcome is known.
The single returned address preserves the selected charge-product page and limit.
Edit results link to its parent list, because the original editor is a modal;
select the matching row there. No invented editor URL is returned. Stored results
do not prove visitor checkout, payment, causality or browser rendering.
Source API paths used for changes:
`point-products/:publProductId/revise`, `point-products/bulk-activate`, and
`point-products/bulk-deactivate` under the core branded-point-system prefix.
The unused product DELETE endpoint is not exposed as a writer. Initial creation
remains separate until its receipt identity and environment-specific price rules
are verified. Its stale repository DTO cannot establish the creation receipt.
## Inputs
| Field | Required here | Contract |
| --- | --- | --- |
| `action` | Yes | one of: `edit`, `visibility`, `create` (by `kind`) |
| `action.publProductId` | Yes | When `action.kind` is `edit`: string; min length 1; max length 256 |
| `action.representationalName` | No | When `action.kind` is `edit`: string; min length 2; max length 20 |
| `action.bonusPoints` | No | When `action.kind` is `edit`: integer; minimum 0 |
| `action.publProductIds` | Yes | When `action.kind` is `visibility`: array; items: string; min length 1; max length 256; min items 1; max items 100 |
| `action.active` | Yes | When `action.kind` is `visibility`: boolean; True makes selected products visible; false hides them. Source-forced visible products cannot be hidden. |
| `action.representationalName` | Yes | When `action.kind` is `create`: string; min length 4; max length 20; Display name of the charge product, 4–20 UTF-16 units after trimming (console limit). |
| `action.priceAmount` | Yes | When `action.kind` is `create`: string; pattern `^(?:0\|[1-9]\d{0,7})(?:\.\d{1,2})?$`; Unformatted KRW or USD amount in the verified channel currency. No commas, signs or rounding. The original screen derives base points from this price. |
| `action.bonusPoints` | No | When `action.kind` is `create`: integer; minimum 0; maximum 9999999999; default `0` |
| `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. |
| `irreversibleConfirmed` | No | `true`; true only after the person confirmed again, when the preview has requiresReconfirmation: the action cannot be undone. |