# IAS Serial Key Manager — WP-CLI Commands **Slug:** `ias-serial-keys`  •  **Version:** 1.1.15  •  **Namespace:** `wp ias serial-keys`  •  **Tier:** Commercial (licence required) > Serial keys & redemption codes: list, generate, import/export, assign, redeem, revoke and delete. All commands accept `--format=`. Mutating commands support `--dry-run` and `--yes`; destructive commands prompt for confirmation unless `--yes` is passed, and any bulk-delete command refuses to run without an explicit scope argument — a required `--filter` on the record-deletion commands, or another mandatory bound such as `--max-age-days` — rather than defaulting to delete-all. ## Authentication & trust model These commands run under WP-CLI, whose trust boundary is **shell access**: anyone who can run `wp` on the server already has full database and PHP access (`wp db query`, `wp eval`). The CLI therefore adds **no separate capability check** — a `current_user_can()` gate would add no real protection and would wrongly refuse commands run without `--user=` (WP-CLI bootstraps as user 0). Protection for the irreversible commands instead comes from `--dry-run` previews, an explicit confirmation prompt (or `--yes`), a mandatory scope argument on any bulk delete (a `--filter`, or another mandatory bound such as `--max-age-days`), and a before-state entry written to the suite-wide CLI audit log. Commands that cannot be undone are flagged with a **⚠ Irreversible** banner below. ## Index - [`wp ias serial-keys assign`](#wp-ias-serial-keys-assign) - [`wp ias serial-keys delete`](#wp-ias-serial-keys-delete) - [`wp ias serial-keys delete-bulk`](#wp-ias-serial-keys-delete-bulk) - [`wp ias serial-keys export`](#wp-ias-serial-keys-export) - [`wp ias serial-keys generate`](#wp-ias-serial-keys-generate) - [`wp ias serial-keys import`](#wp-ias-serial-keys-import) - [`wp ias serial-keys inspect`](#wp-ias-serial-keys-inspect) - [`wp ias serial-keys list`](#wp-ias-serial-keys-list) - [`wp ias serial-keys redeem`](#wp-ias-serial-keys-redeem) - [`wp ias serial-keys revoke`](#wp-ias-serial-keys-revoke) - [`wp ias serial-keys show`](#wp-ias-serial-keys-show) - [`wp ias serial-keys stock`](#wp-ias-serial-keys-stock) - [`wp ias serial-keys whose`](#wp-ias-serial-keys-whose) ## `wp ias serial-keys assign` Assign a free-pool key to a specific customer (support tool). The serial-key schema binds a customer to a key through a WooCommerce order, so this creates a $0 order for the customer, binds the named key to it via IAS\SerialKeys\Database::assign_key(), and completes the order (mirroring the redemption fulfillment path). Completing the order fires the normal fulfillment hooks (key-delivery email, and licence/ownership grants if the product is otherwise configured). ```bash wp ias serial-keys assign [--dry-run] [--yes] [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `` | yes | positional | The serial key string (must currently be in the available pool). | | `` | yes | positional | Customer reference — numeric WP user ID or email. | | `[--dry-run]` | no | flag | Report what would happen without creating an order or assigning the key. | | `[--yes]` | no | flag | Skip the confirmation prompt. | | `[--format=]` | no | flag (value) | Output format. | **Example:** ```bash wp ias serial-keys assign IAS-ABCD-1234-EFGH customer@example.com ``` **Related:** `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list`, `wp ias serial-keys redeem` ## `wp ias serial-keys delete` > **⚠ Irreversible — `--dry-run` first.** This command permanently destroys data or applies a terminal state that cannot be undone from the CLI. Preview the exact effect with `--dry-run`, then re-run with `--yes` once you are certain. Permanently delete a single serial key. Resolves the key via IAS\SerialKeys\Database::get_key_by_serial() and removes the row with IAS\SerialKeys\Database::delete_key(). This is NON-RECOVERABLE: the key string and any pool/assignment record for it are gone. Use `revoke` instead if you want to retire a key while keeping the row for audit/history. Note on --keep-audit: serial keys keep NO per-key history table, so this flag has no database effect — there is no per-key log to retain. It is accepted for cross-plugin CLI parity and recorded in the audit context for transparency. ```bash wp ias serial-keys delete [--keep-audit] [--dry-run] [--yes] [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `` | yes | positional | The serial key string to delete. | | `[--keep-audit]` | no | flag | No-op for serial keys (there is no per-key log to retain); recorded for cross-plugin CLI parity only. | | `[--dry-run]` | no | flag | Report what would be deleted without removing anything. | | `[--yes]` | no | flag | Skip the confirmation prompt. | | `[--format=]` | no | flag (value) | Output format. | **Returns:** A JSON object: { dry_run, action, key, product_id, status, keep_audit, deleted }. **Example:** ```bash wp ias serial-keys delete IAS-ABCD-1234-EFGH --dry-run wp ias serial-keys delete IAS-ABCD-1234-EFGH --yes ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list`, `wp ias serial-keys redeem` ## `wp ias serial-keys delete-bulk` > **⚠ Irreversible — `--dry-run` first.** This command permanently destroys data or applies a terminal state that cannot be undone from the CLI. Preview the exact effect with `--dry-run`, then re-run with `--yes` once you are certain. Permanently delete every serial key matching a JSON filter (bulk, destructive). This is a bulk destructive operation and therefore REQUIRES an explicit --filter= selector; it refuses to run without one and has no `--all` escape hatch. The filter is resolved with IAS\SerialKeys\Database::get_keys() and each matched row is removed with IAS\SerialKeys\Database::delete_key(). NON-RECOVERABLE. A single run processes at most 1000 keys. The true (uncapped) match count is reported as `total_matching` and, when it exceeds the per-run cap, `capped` is true and a warning is emitted — re-run the command after each batch to delete the remainder. ```bash wp ias serial-keys delete-bulk --filter= [--dry-run] [--yes] [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `--filter=` | yes | flag (value) | Required JSON selector. Recognised keys: product_id (int), status (available\|sold\|revoked), search (substring of the key). Must select at least one constraint. | | `[--dry-run]` | no | flag | Report how many keys match without deleting anything. | | `[--yes]` | no | flag | Skip the confirmation prompt. | | `[--format=]` | no | flag (value) | Output format. | **Returns:** A JSON object: { dry_run, action, filter, total_matching, matched, capped, deleted }. **Example:** ```bash wp ias serial-keys delete-bulk --filter='{"status":"revoked"}' --dry-run wp ias serial-keys delete-bulk --filter='{"product_id":42,"status":"available"}' --yes ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list`, `wp ias serial-keys redeem` ## `wp ias serial-keys export` Export serial keys to a CSV or JSON file. Reads keys via IAS\SerialKeys\Database::get_keys() (optionally filtered) and writes them to . This mutates the filesystem (not the database) but is audited so exports are traceable. Honours the licensed `ias_sk_can_export` gate for the actual write. CSV cells are neutralised against spreadsheet formula injection, matching the admin export. NOTE: unlike every other command, `export --format` selects the on-disk FILE format (csv|json) — not the suite-wide `--format=` output-rendering flag. The dry-run summary is always emitted as JSON. ```bash wp ias serial-keys export --file= [--format=] [--product=] [--status=] [--dry-run] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `--file=` | yes | flag (value) | Destination file path. | | `[--format=]` | no | flag (value) | Export FILE format (csv or json) — see the note above; this overloads the conventional output-format flag. | | `[--product=]` | no | flag (value) | Restrict to one product (numeric ID or SKU). | | `[--status=]` | no | flag (value) | Restrict to keys with this status (available or sold). | | `[--dry-run]` | no | flag | Report how many keys would be exported without writing the file. | **Example:** ```bash wp ias serial-keys export --file=keys.csv --product=42 wp ias serial-keys export --file=keys.json --format=json --status=available ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list`, `wp ias serial-keys redeem` ## `wp ias serial-keys generate` Bulk-generate serial keys for a product. Mirrors the admin Generate screen: delegates to IAS\SerialKeys\Key_Generator::generate_keys(), which enforces the licensed batch ceiling (ias_sk_max_batch_size), pattern/prefix formatting and uniqueness. Keys land in the unassigned pool. With --customer the freshly generated keys are then assigned to that customer via a $0 order (mirroring the redemption fulfillment path). ```bash wp ias serial-keys generate [--customer=] [--prefix=] [--dry-run] [--yes] [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `` | yes | positional | Product reference — numeric ID or SKU. | | `` | yes | positional | Number of keys to generate. | | `[--customer=]` | no | flag (value) | Assign the generated keys to this customer (numeric WP user ID or email). | | `[--prefix=]` | no | flag (value) | Override the key prefix for this batch. | | `[--dry-run]` | no | flag | Validate and report what would be generated without writing anything. | | `[--yes]` | no | flag | Skip the confirmation prompt. | | `[--format=]` | no | flag (value) | Output format. | **Example:** ```bash wp ias serial-keys generate 42 100 wp ias serial-keys generate SKU-PRO 5 --customer=customer@example.com --dry-run ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list`, `wp ias serial-keys redeem` ## `wp ias serial-keys import` Import serial keys for a product from a CSV/TXT file (one key per line). Additive importer: delegates to IAS\SerialKeys\Database::import_keys(), which inserts new keys and skips any that already exist. The underlying importer is insert-only — there is no in-place update path — so --update-existing only affects how pre-existing keys are reported, not stored (existing keys are always skipped). Honours the licensed `ias_sk_can_import` gate for the actual write; the dry-run preview is always available. ```bash wp ias serial-keys import --product= --file= [--update-existing] [--dry-run] [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `--product=` | yes | flag (value) | Product the keys belong to (numeric ID or SKU). | | `--file=` | yes | flag (value) | Path to the import file (one key per line; first CSV column is used). | | `[--update-existing]` | no | flag | Reserved. The importer is insert-only, so existing keys are still skipped; this flag is recorded for traceability only. | | `[--dry-run]` | no | flag | Parse and classify each row (new vs already-present) without importing. | | `[--format=]` | no | flag (value) | Output format. | **Example:** ```bash wp ias serial-keys import --product=42 --file=keys.csv --dry-run wp ias serial-keys import --product=42 --file=keys.csv ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys inspect`, `wp ias serial-keys list`, `wp ias serial-keys redeem` ## `wp ias serial-keys inspect` Report the plugin slug, version and CLI environment. ```bash wp ias serial-keys inspect [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `[--format=]` | no | flag (value) | Output format. | **Example:** ```bash wp ias serial-keys inspect ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys list`, `wp ias serial-keys redeem` ## `wp ias serial-keys list` List serial keys with optional filters and pagination. ```bash wp ias serial-keys list [--customer=] [--status=] [--product=] [--page=] [--per-page=] [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `[--customer=]` | no | flag (value) | Restrict to keys assigned to this customer (numeric WP user ID or email). | | `[--status=]` | no | flag (value) | Filter by status. | | `[--product=]` | no | flag (value) | Filter by product (numeric ID or SKU). | | `[--page=]` | no | flag (value) | Page of results (1-based). | | `[--per-page=]` | no | flag (value) | Results per page (capped at 1000). | | `[--format=]` | no | flag (value) | Output format. | **Example:** ```bash wp ias serial-keys list --status=available --product=42 wp ias serial-keys list --customer=customer@example.com --format=json ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys redeem` ## `wp ias serial-keys redeem` Redeem a redemption code on a customer's behalf (support tool). Delegates to IAS\SerialKeys\Database::redeem_code(), the exact two-phase atomic path the storefront uses: it claims the code, creates a $0 order, assigns a key, and completes the order. ```bash wp ias serial-keys redeem [--customer=] [--email=] [--dry-run] [--yes] [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `` | yes | positional | The redemption code. | | `[--customer=]` | no | flag (value) | Redeem on behalf of this account (numeric WP user ID or email). Omit to redeem as a guest, in which case --email is required. | | `[--email=]` | no | flag (value) | Guest email for the redemption when no --customer account is given. | | `[--dry-run]` | no | flag | Validate the code without redeeming it. | | `[--yes]` | no | flag | Skip the confirmation prompt. | | `[--format=]` | no | flag (value) | Output format. | **Example:** ```bash wp ias serial-keys redeem WELCOME-2026 --customer=42 wp ias serial-keys redeem WELCOME-2026 --email=guest@example.com --dry-run ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list` ## `wp ias serial-keys revoke` > **⚠ Irreversible — `--dry-run` first.** This command permanently destroys data or applies a terminal state that cannot be undone from the CLI. Preview the exact effect with `--dry-run`, then re-run with `--yes` once you are certain. Retire a serial key by setting a terminal `revoked` status. Serial keys natively use only the `available` and `sold` statuses, and there is no public status setter, so this updates the row directly to a terminal `revoked` status. A revoked key is neither resold (the available pool query filters status='available') nor validated as sold, but the row is preserved (unlike `delete`). The product's available-pool cache is invalidated so the change takes effect immediately. ```bash wp ias serial-keys revoke [--reason=] [--dry-run] [--yes] [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `` | yes | positional | The serial key string to revoke. | | `[--reason=]` | no | flag (value) | Optional free-text reason, recorded in the audit context. | | `[--dry-run]` | no | flag | Report what would be revoked without changing anything. | | `[--yes]` | no | flag | Skip the confirmation prompt. | | `[--format=]` | no | flag (value) | Output format. | **Returns:** A JSON object: { dry_run, action, key, product_id, status_before, status_after, reason, revoked, already_applied }. `already_applied` is true when the key was already revoked (a no-op re-run); `revoked` is then false. **Example:** ```bash wp ias serial-keys revoke IAS-ABCD-1234-EFGH --dry-run wp ias serial-keys revoke IAS-ABCD-1234-EFGH --reason="chargeback" --yes ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list` ## `wp ias serial-keys show` Show the full state of one serial key. ```bash wp ias serial-keys show [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `` | yes | positional | The serial key string. | | `[--format=]` | no | flag (value) | Output format. | **Example:** ```bash wp ias serial-keys show IAS-ABCD-1234-EFGH --format=json ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list` ## `wp ias serial-keys stock` Report unassigned / assigned key counts per product. ```bash wp ias serial-keys stock [--product=] [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `[--product=]` | no | flag (value) | Restrict the report to one product (numeric ID or SKU). | | `[--format=]` | no | flag (value) | Output format. | **Example:** ```bash wp ias serial-keys stock wp ias serial-keys stock --product=42 --format=json ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list` ## `wp ias serial-keys whose` Resolve a serial key to its owning order and customer. ```bash wp ias serial-keys whose [--format=] ``` | Argument | Required | Type | Description | |----------|----------|------|-------------| | `` | yes | positional | The serial key string. | | `[--format=]` | no | flag (value) | Output format. | **Example:** ```bash wp ias serial-keys whose IAS-ABCD-1234-EFGH ``` **Related:** `wp ias serial-keys assign`, `wp ias serial-keys delete`, `wp ias serial-keys delete-bulk`, `wp ias serial-keys export`, `wp ias serial-keys generate`, `wp ias serial-keys import`, `wp ias serial-keys inspect`, `wp ias serial-keys list`