API, MCP & CLI
API: Command-line tool
Install the listingview command-line tool, sign in with an API key, run every API route as a command, rehearse with dry runs, stage Etsy drafts, and script it safely with JSON output, exit codes and safe re-runs.
Updated
listingview runs the ListingView API from your terminal, your scripts and your agents. Every API route is a command. The command list comes from the API itself, so the two always match.
You need an API key first. API: Getting started shows how to make one, and Using the ListingView API, MCP server & CLI explains which kind of key to choose.
Install
You need Node.js 18.3 or newer. The CLI has no other dependencies.
npm install -g @listingview/cli listingview --help
Or run it without installing:
npx @listingview/cli --help
The examples below use listingview. With npx, write npx @listingview/cli instead.
Sign in
For agents, scripts and CI, put the key in the environment:
export LISTINGVIEW_API_KEY=lv_live_… listingview auth status
On your own computer you can save the key instead:
listingview auth login
auth login asks for the key without showing it, or reads it from stdin: printf %s "$KEY" | listingview auth login --key-stdin. It checks the key with GET /api/v1/ping before it saves it (skip that with --no-verify). The key is saved in ~/.listingview/credentials, readable only by you.
Check which key is in use
listingview auth status shows which key is in use, where it came from, which API it talks to and the key's scopes. It prints only the start of the key, never the whole key. Add --offline to skip the call to the API.
When more than one key is around, the first match wins:
--api-key <key>. This works, but the CLI warns you: it ends up in your shell history.--profile <name>LISTINGVIEW_API_KEYThe saved profile named by
LISTINGVIEW_PROFILE, ordefault.
Profiles keep several keys side by side: listingview auth login --profile drafts, then listingview --profile drafts …. Drafting and publishing never share a key, so save a Drafting Agent key and a Publisher key under two profiles. A test key can have its own profile too, for example --profile test.
listingview auth logout removes the saved key from this computer. It doesn't revoke the key. Revoke keys in ListingView under Settings → API Keys.
Environment variables
Variable | Default | What it does |
|---|---|---|
| none | The API key. |
|
| The API origin. |
|
| Which saved profile to use. |
|
| Where the saved keys and the command cache live. |
| none | Use this file as the command list. |
|
| Seconds per request. |
--base-url overrides LISTINGVIEW_BASE_URL. The CLI sends your key only over https://; plain http:// is refused except for localhost.
Commands
The command list comes from the API's describe output. Nobody writes it by hand.
listingview --help # every command listingview etsy-drafts --help # the commands under one word listingview catalog listings list --help # one command's arguments listingview describe --json # the full machine-readable list listingview describe --refresh # fetch the latest list with your key
describe --refresh fetches the live list with your key, saves it, and marks which commands your key can call. Without it, the CLI uses the list it was installed with.
Each command maps to one API route and, where there is one, to an MCP tool. Each line below reads: command · REST route · MCP tool. --help on a command's first word, such as listingview etsy-drafts --help, shows the exact words your installed list has. The API reference documents every route.
Account and discovery
listingview ping·GET /api/v1/ping· no MCP toollistingview describe·GET /api/v1/describe· no MCP toollistingview usage get·GET /api/v1/usage·get_account_usagelistingview usage ai-tokens·GET /api/v1/usage/ai-tokens·get_account_usage
Market research
Every research route is a command under listingview research. Run listingview research --help to list them. Each maps to one of the research tools in API: Connect AI apps.
Your shop
listingview my-shop·GET /api/v1/my-shop·my_shop_performancelistingview my-shop performance·GET /api/v1/my-shop/performance·my_shop_performancelistingview my-shop listing-scores·GET /api/v1/my-shop/listing-scores·my_shop_performance
Listings in ListingView
listingview catalog listings list·GET /api/v1/catalog/listings·list_my_listingslistingview catalog listings get·GET /api/v1/catalog/listings/{listing_id}·get_listinglistingview catalog listings resolve·GET /api/v1/catalog/listings/resolve·get_listinglistingview catalog listings publish-checklist·GET /api/v1/catalog/listings/{listing_id}/publish-checklist·get_listinglistingview catalog listings create·POST /api/v1/catalog/listings·create_local_listinglistingview catalog listings update·PUT /api/v1/catalog/listings/{listing_id}·update_listinglistingview catalog listings images set·PUT /api/v1/catalog/listings/{listing_id}/images·update_listinglistingview catalog listings ai-enhance·POST /api/v1/catalog/listings/{listing_id}/ai-enhance·enhance_listing_with_ailistingview catalog listings lookup·POST /api/v1/catalog/listings/lookup·get_listingwithetsy_listing_ids: up to 100 Etsy listing ids at once, with live state, print-on-demand prices or live inventory
Bulk jobs and AI copy
listingview catalog bulk create·POST /api/v1/catalog/bulk/create·bulk_edit_listings. It requires an idempotency key, so a re-run of the same command returns the same joblistingview catalog bulk edit·POST /api/v1/catalog/bulk/edit·bulk_edit_listingslistingview catalog bulk jobs status·GET /api/v1/catalog/bulk/jobs/{job_id}·get_bulk_job_status. It also reads reprice jobs (lbj_…)listingview ai listing-copy·POST /api/v1/ai/listing-copy·enhance_listing_with_ai
Asset library
listingview assets upload· runs the whole upload: begin, upload, finalize, wait (see API: Uploads).--purpose digital_fileuploads delivery files · no MCP toollistingview assets uploads begin·POST /api/v1/assets/uploads·add_assetslistingview assets uploads finalize·POST /api/v1/assets/uploads/finalize·add_assetslistingview assets images import·POST /api/v1/assets/images/import·add_assetslistingview assets images list·GET /api/v1/assets/images·list_assets.--kind deliverablelists delivery fileslistingview assets files get·GET /api/v1/assets/files·list_assets.--idslooks up to 50 files by id, of any typelistingview assets files update·PATCH /api/v1/assets/files/{file_id}·organize_assetslistingview assets files duplicate·POST /api/v1/assets/files/{file_id}/duplicate·organize_assetslistingview assets files membership·POST /api/v1/assets/files/membership·organize_assetslistingview assets collections·GET /api/v1/assets/collections·list_assetslistingview assets collections create·POST /api/v1/assets/collections·organize_assetslistingview assets collections rename·PATCH /api/v1/assets/collections/{collection_id}·organize_assetslistingview assets collections move·POST /api/v1/assets/collections/{collection_id}/move·organize_assets
Presets
listingview presets list·GET /api/v1/presets·list_presetslistingview presets get·GET /api/v1/presets/{preset_id}·list_presets.--includeadds sections;--include specreturns the full preset as a create bodylistingview presets create·POST /api/v1/presets·manage_presetlistingview presets update·PATCH /api/v1/presets/{preset_id}·manage_presetlistingview presets copy·POST /api/v1/presets/{preset_id}/copy·manage_presetlistingview presets delete·DELETE /api/v1/presets/{preset_id}·delete_preset_or_draftwithkind: "preset"
Preset building blocks
listingview pod-products list·GET /api/v1/pod-products·list_presetswithview: "pod_products"listingview pod-products get·GET /api/v1/pod-products/{product_id}·list_presetswithview: "pod_products"andproduct_idlistingview pod-products providers get·GET /api/v1/pod-products/{product_id}/providers/{provider_id}·list_presetswithview: "pod_products",product_idandprovider_idlistingview etsy-taxonomy properties·GET /api/v1/etsy-taxonomy/{taxonomy_id}/properties·list_presetswithview: "category_attributes"listingview my-shop profiles·GET /api/v1/my-shop/profiles·list_presetswithview: "shop_profiles"listingview mockup-templates list·GET /api/v1/mockup-templates·list_presetswithview: "mockup_templates"
Etsy drafts
listingview etsy-drafts create·POST /api/v1/etsy-drafts·create_etsy_drafts.--stagestages the batch instead (operation: "stage"over MCP)listingview etsy-drafts jobs status·GET /api/v1/etsy-drafts/jobs/{job_id}·get_bulk_job_statuslistingview etsy-drafts jobs list·GET /api/v1/etsy-drafts/jobs·get_bulk_job_statuswithlist: "jobs": your Etsy-draft job historylistingview etsy-drafts staged list·GET /api/v1/etsy-drafts/staged·get_bulk_job_statuswithlist: "staged": your open staged batcheslistingview etsy-drafts staged get·GET /api/v1/etsy-drafts/staged/{draft_id}·get_bulk_job_statuswithdraft_id: one batch as it is nowlistingview etsy-drafts staged update·PATCH /api/v1/etsy-drafts/staged/{draft_id}·create_etsy_draftswithoperation: "update"listingview etsy-drafts staged submit·POST /api/v1/etsy-drafts/staged/{draft_id}/submit·create_etsy_draftswithoperation: "submit"listingview etsy-drafts staged delete·DELETE /api/v1/etsy-drafts/staged/{draft_id}·delete_preset_or_draftwithkind: "staged_batch"listingview catalog listings delete·DELETE /api/v1/catalog/listings/{listing_id}·delete_preset_or_draftwithkind: "etsy_draft": deletes an Etsy draft that ListingView made
Publishing
The CLI doesn't have live-change commands yet: publishing, pushing and repricing aren't in its command list. Use the REST routes or the push_listing_live MCP tool, which Publish and reprice live listings covers.
Arguments
Path parameters come first, in order:
listingview catalog listings get 91234.Everything else is a flag:
--status draftor--status=draft. Booleans take--flagor--no-flag. Repeat a flag to send a list:--ids 88123 --ids 88207.JSON arguments take inline JSON,
@file.json, or-to read stdin.--inputtakes the whole input as JSON. Flags override its keys.
The CLI checks types, required arguments, unknown flags and the API's published size limits before it sends anything. A mistake exits with code 2 and costs nothing.
JSON output for agents
When stdout isn't a terminal (a pipe, a script, an agent), stdout carries exactly one JSON document: the API's answer, or the error object
{"error": {…}}. Notes and warnings go to stderr.In a terminal you get a readable layout.
--jsonor--no-jsonpicks one explicitly.--quiethides notes.--verboselogs each request and its timing to stderr, never the headers, so your key stays out of logs.API commands never prompt, so an agent never waits for a keypress.
listingview catalog listings list --status draft --json | jq '.listings[].title'
The error object is the same one the REST API returns. API: Getting started explains its fields and the retry rules for agents, and every code is on the errors page.
Exit codes
Code | Name | Meaning |
|---|---|---|
0 |
| Success. |
1 |
| Any other failure: not found, a conflict or precondition on your data, or an internal error. Quote the |
2 |
| The request was malformed or out of bounds ( |
3 |
| The API key is missing, invalid, revoked or expired. |
4 |
| The key's scopes or the account's plan don't allow this call, or the feature is off right now. |
5 |
| A budget or rate limit was hit. Wait for the reset ( |
6 |
| A live change on Etsy printed its preview and is waiting for you: run the printed line with |
7 |
| Etsy, Printify, the AI provider or a ListingView dependency failed or is unavailable. Retry later. |
8 |
| A batch finished with some items failed. The CLI prints a per-item table. |
9 |
| Some items have an unknown outcome. Check the shop before retrying, and never resubmit them. |
10 |
|
|
Retries and idempotency
Only retryable errors are retried. The CLI retries only errors the API marks retryable. It waits as long as
retry_afterasks, up to 30 seconds, and makes at most--retriesextra attempts (default 2). If the API asks for a longer wait, the CLI stops with the error instead, so run the command again later.Every change carries an idempotency key. Pass
--idempotency-key <key>to make re-runs safe. For commands that require a key, such asetsy-drafts create,assets uploads beginandcatalog bulk create, the CLI makes one from the command and its input when you don't pass one and prints it on stderr. Running the same command again then returns the first result instead of repeating the work. Any other change gets a new random key on each run, which protects only that run's own retries.No clear answer means exit code 9. If a change ends without a clear answer, the CLI stops with exit code 9 and prints the idempotency key to retry with. Re-run with that key: if the first attempt went through, you get its result back instead of a second change.
Dry runs
With an lv_test_ key, every change is a dry run. The answer shows what would happen, with "dry_run": true, and nothing is written, sent to Etsy or charged. Reads still run for real and use credits as usual.
--dry-run makes sure of it. It needs an lv_test_ key and refuses to run with a live key, so it can never write by mistake:
listingview --profile test etsy-drafts create --stage --shop-id 38123456 --preset-id 1667 --items items.json --dry-run
See Rehearse with a test key in API: Getting started for what a test key checks for real and what comes back unverified.
Upload designs and delivery files
assets upload runs the whole upload protocol from API: Uploads and waits until each file is ready:
listingview assets upload front.png back.png --collection 311 listingview assets upload designs/*.png --json | jq '.[] | select(.ready) | .file_id' listingview assets upload --purpose digital_file printable-planner-2027.pdf
--purposesays what you're uploading:design(the default), ordigital_filefor the files a digital listing delivers to buyers. Delivery files have their own file types and size limit (see API: Uploads).For designs, it checks each file before uploading and refuses anything that isn't PNG, JPEG or WebP. The type is read from the file's bytes, not its name.
Your key is never sent to storage, and upload URLs are never printed.
It waits until every file is ready.
--no-waitreturns right after the upload;--wait-timeout <seconds>changes how long it waits.Running the same command again is safe. Files already in your library show "already in library" and aren't uploaded or counted twice.
Exit codes: 0 every file is ready, 2 a file was refused, quarantined or failed, 8 some files didn't upload (running it again is safe), 10 the wait ran out (the files keep processing).
Etsy drafts
With a Drafting Agent key, turn a preset and your designs into Etsy drafts:
listingview presets list listingview presets get 1667 # in a terminal: the design slots (A, B, …) to fill listingview presets get 1667 --include spec # the whole preset, in the shape presets create accepts listingview etsy-drafts create --shop-id 38123456 --preset-id 1667 --items items.json --wait listingview etsy-drafts jobs status edj_48213 --watch
--itemsreads a JSON array of items from a file, or from stdin with-.Without
--idempotency-key, the key is made from the shop, the preset and the items. Running the same command again, even much later, returns the same job instead of making new drafts. Pass a new--idempotency-keyto make a second batch on purpose.--waitfollows the job until it finishes.--watchalso prints each item as it lands.Exit codes: 0 every item became a draft, 8 some items failed, were skipped or were cancelled, 9 an item's outcome is unknown (check your shop and never resubmit it), 10 the wait ran out (the job keeps running).
Stage a batch for review
Add --stage to save the batch for review in ListingView instead of drafting it at once. Nothing reaches Etsy yet.
listingview etsy-drafts create --stage --shop-id 38123456 --preset-id 1667 --items items.json \ --idempotency-key stage-2026-10-26-batch-01
The answer has the batch's
draft_id, itsrevisionand areview_urlthat opens Saved listings in ListingView.Keep the idempotency key. If the answer is lost, running the same command with the same key returns the same batch while it is open.
Staging takes the copy you already have. Inline AI copy is refused when you stage, so write it first with
listingview ai listing-copy.Then read, edit, submit or discard the batch with
etsy-drafts staged get,update,submitanddelete;etsy-drafts staged listlists your open batches. A submit sends the batch as it is now, including edits made in ListingView, and returns ajob_idthatetsy-drafts jobs statusfollows.
Stage Etsy drafts, review them in ListingView, then submit walks through the whole loop, including edits and conflicts.
Drafts are hidden from shoppers. Publish them with a Publisher key, or with the Publish button in ListingView. For the checks ListingView runs before any draft reaches Etsy, see Using the ListingView API, MCP server & CLI.
Live changes on Etsy
The CLI doesn't publish, push or reprice live listings yet. Publish drafts with the Publish button in ListingView, or through the REST API or MCP with a Publisher key. Publish and reprice live listings covers the confirm step those calls go through.
Related features
API: Getting started: keys, test keys, idempotency, pagination and the error shape
API: Connect AI apps: the same actions as MCP tools in Claude Code or Cursor
API: Uploads: what
assets uploaddoes step by stepBuild presets with the API:
presets get --include specand the building blocksStage Etsy drafts, review them in ListingView, then submit: staged batches from start to finish
Publish and reprice live listings: the Publisher key and the confirm step
API: Limits & budgets: what commands cost and what exit code 5 means for your budget
API reference: every route, generated live from the API
Using the ListingView API, MCP server & CLI: the seller guide to keys, presets and Etsy drafts
listingview runs the ListingView API from your terminal, your scripts and your agents. Every API route is a command. The command list comes from the API itself, so the two always match.
You need an API key first. API: Getting started shows how to make one, and Using the ListingView API, MCP server & CLI explains which kind of key to choose.
Install
You need Node.js 18.3 or newer. The CLI has no other dependencies.
npm install -g @listingview/cli listingview --help
Or run it without installing:
npx @listingview/cli --help
The examples below use listingview. With npx, write npx @listingview/cli instead.
Sign in
For agents, scripts and CI, put the key in the environment:
export LISTINGVIEW_API_KEY=lv_live_… listingview auth status
On your own computer you can save the key instead:
listingview auth login
auth login asks for the key without showing it, or reads it from stdin: printf %s "$KEY" | listingview auth login --key-stdin. It checks the key with GET /api/v1/ping before it saves it (skip that with --no-verify). The key is saved in ~/.listingview/credentials, readable only by you.
Check which key is in use
listingview auth status shows which key is in use, where it came from, which API it talks to and the key's scopes. It prints only the start of the key, never the whole key. Add --offline to skip the call to the API.
When more than one key is around, the first match wins:
--api-key <key>. This works, but the CLI warns you: it ends up in your shell history.--profile <name>LISTINGVIEW_API_KEYThe saved profile named by
LISTINGVIEW_PROFILE, ordefault.
Profiles keep several keys side by side: listingview auth login --profile drafts, then listingview --profile drafts …. Drafting and publishing never share a key, so save a Drafting Agent key and a Publisher key under two profiles. A test key can have its own profile too, for example --profile test.
listingview auth logout removes the saved key from this computer. It doesn't revoke the key. Revoke keys in ListingView under Settings → API Keys.
Environment variables
Variable | Default | What it does |
|---|---|---|
| none | The API key. |
|
| The API origin. |
|
| Which saved profile to use. |
|
| Where the saved keys and the command cache live. |
| none | Use this file as the command list. |
|
| Seconds per request. |
--base-url overrides LISTINGVIEW_BASE_URL. The CLI sends your key only over https://; plain http:// is refused except for localhost.
Commands
The command list comes from the API's describe output. Nobody writes it by hand.
listingview --help # every command listingview etsy-drafts --help # the commands under one word listingview catalog listings list --help # one command's arguments listingview describe --json # the full machine-readable list listingview describe --refresh # fetch the latest list with your key
describe --refresh fetches the live list with your key, saves it, and marks which commands your key can call. Without it, the CLI uses the list it was installed with.
Each command maps to one API route and, where there is one, to an MCP tool. Each line below reads: command · REST route · MCP tool. --help on a command's first word, such as listingview etsy-drafts --help, shows the exact words your installed list has. The API reference documents every route.
Account and discovery
listingview ping·GET /api/v1/ping· no MCP toollistingview describe·GET /api/v1/describe· no MCP toollistingview usage get·GET /api/v1/usage·get_account_usagelistingview usage ai-tokens·GET /api/v1/usage/ai-tokens·get_account_usage
Market research
Every research route is a command under listingview research. Run listingview research --help to list them. Each maps to one of the research tools in API: Connect AI apps.
Your shop
listingview my-shop·GET /api/v1/my-shop·my_shop_performancelistingview my-shop performance·GET /api/v1/my-shop/performance·my_shop_performancelistingview my-shop listing-scores·GET /api/v1/my-shop/listing-scores·my_shop_performance
Listings in ListingView
listingview catalog listings list·GET /api/v1/catalog/listings·list_my_listingslistingview catalog listings get·GET /api/v1/catalog/listings/{listing_id}·get_listinglistingview catalog listings resolve·GET /api/v1/catalog/listings/resolve·get_listinglistingview catalog listings publish-checklist·GET /api/v1/catalog/listings/{listing_id}/publish-checklist·get_listinglistingview catalog listings create·POST /api/v1/catalog/listings·create_local_listinglistingview catalog listings update·PUT /api/v1/catalog/listings/{listing_id}·update_listinglistingview catalog listings images set·PUT /api/v1/catalog/listings/{listing_id}/images·update_listinglistingview catalog listings ai-enhance·POST /api/v1/catalog/listings/{listing_id}/ai-enhance·enhance_listing_with_ailistingview catalog listings lookup·POST /api/v1/catalog/listings/lookup·get_listingwithetsy_listing_ids: up to 100 Etsy listing ids at once, with live state, print-on-demand prices or live inventory
Bulk jobs and AI copy
listingview catalog bulk create·POST /api/v1/catalog/bulk/create·bulk_edit_listings. It requires an idempotency key, so a re-run of the same command returns the same joblistingview catalog bulk edit·POST /api/v1/catalog/bulk/edit·bulk_edit_listingslistingview catalog bulk jobs status·GET /api/v1/catalog/bulk/jobs/{job_id}·get_bulk_job_status. It also reads reprice jobs (lbj_…)listingview ai listing-copy·POST /api/v1/ai/listing-copy·enhance_listing_with_ai
Asset library
listingview assets upload· runs the whole upload: begin, upload, finalize, wait (see API: Uploads).--purpose digital_fileuploads delivery files · no MCP toollistingview assets uploads begin·POST /api/v1/assets/uploads·add_assetslistingview assets uploads finalize·POST /api/v1/assets/uploads/finalize·add_assetslistingview assets images import·POST /api/v1/assets/images/import·add_assetslistingview assets images list·GET /api/v1/assets/images·list_assets.--kind deliverablelists delivery fileslistingview assets files get·GET /api/v1/assets/files·list_assets.--idslooks up to 50 files by id, of any typelistingview assets files update·PATCH /api/v1/assets/files/{file_id}·organize_assetslistingview assets files duplicate·POST /api/v1/assets/files/{file_id}/duplicate·organize_assetslistingview assets files membership·POST /api/v1/assets/files/membership·organize_assetslistingview assets collections·GET /api/v1/assets/collections·list_assetslistingview assets collections create·POST /api/v1/assets/collections·organize_assetslistingview assets collections rename·PATCH /api/v1/assets/collections/{collection_id}·organize_assetslistingview assets collections move·POST /api/v1/assets/collections/{collection_id}/move·organize_assets
Presets
listingview presets list·GET /api/v1/presets·list_presetslistingview presets get·GET /api/v1/presets/{preset_id}·list_presets.--includeadds sections;--include specreturns the full preset as a create bodylistingview presets create·POST /api/v1/presets·manage_presetlistingview presets update·PATCH /api/v1/presets/{preset_id}·manage_presetlistingview presets copy·POST /api/v1/presets/{preset_id}/copy·manage_presetlistingview presets delete·DELETE /api/v1/presets/{preset_id}·delete_preset_or_draftwithkind: "preset"
Preset building blocks
listingview pod-products list·GET /api/v1/pod-products·list_presetswithview: "pod_products"listingview pod-products get·GET /api/v1/pod-products/{product_id}·list_presetswithview: "pod_products"andproduct_idlistingview pod-products providers get·GET /api/v1/pod-products/{product_id}/providers/{provider_id}·list_presetswithview: "pod_products",product_idandprovider_idlistingview etsy-taxonomy properties·GET /api/v1/etsy-taxonomy/{taxonomy_id}/properties·list_presetswithview: "category_attributes"listingview my-shop profiles·GET /api/v1/my-shop/profiles·list_presetswithview: "shop_profiles"listingview mockup-templates list·GET /api/v1/mockup-templates·list_presetswithview: "mockup_templates"
Etsy drafts
listingview etsy-drafts create·POST /api/v1/etsy-drafts·create_etsy_drafts.--stagestages the batch instead (operation: "stage"over MCP)listingview etsy-drafts jobs status·GET /api/v1/etsy-drafts/jobs/{job_id}·get_bulk_job_statuslistingview etsy-drafts jobs list·GET /api/v1/etsy-drafts/jobs·get_bulk_job_statuswithlist: "jobs": your Etsy-draft job historylistingview etsy-drafts staged list·GET /api/v1/etsy-drafts/staged·get_bulk_job_statuswithlist: "staged": your open staged batcheslistingview etsy-drafts staged get·GET /api/v1/etsy-drafts/staged/{draft_id}·get_bulk_job_statuswithdraft_id: one batch as it is nowlistingview etsy-drafts staged update·PATCH /api/v1/etsy-drafts/staged/{draft_id}·create_etsy_draftswithoperation: "update"listingview etsy-drafts staged submit·POST /api/v1/etsy-drafts/staged/{draft_id}/submit·create_etsy_draftswithoperation: "submit"listingview etsy-drafts staged delete·DELETE /api/v1/etsy-drafts/staged/{draft_id}·delete_preset_or_draftwithkind: "staged_batch"listingview catalog listings delete·DELETE /api/v1/catalog/listings/{listing_id}·delete_preset_or_draftwithkind: "etsy_draft": deletes an Etsy draft that ListingView made
Publishing
The CLI doesn't have live-change commands yet: publishing, pushing and repricing aren't in its command list. Use the REST routes or the push_listing_live MCP tool, which Publish and reprice live listings covers.
Arguments
Path parameters come first, in order:
listingview catalog listings get 91234.Everything else is a flag:
--status draftor--status=draft. Booleans take--flagor--no-flag. Repeat a flag to send a list:--ids 88123 --ids 88207.JSON arguments take inline JSON,
@file.json, or-to read stdin.--inputtakes the whole input as JSON. Flags override its keys.
The CLI checks types, required arguments, unknown flags and the API's published size limits before it sends anything. A mistake exits with code 2 and costs nothing.
JSON output for agents
When stdout isn't a terminal (a pipe, a script, an agent), stdout carries exactly one JSON document: the API's answer, or the error object
{"error": {…}}. Notes and warnings go to stderr.In a terminal you get a readable layout.
--jsonor--no-jsonpicks one explicitly.--quiethides notes.--verboselogs each request and its timing to stderr, never the headers, so your key stays out of logs.API commands never prompt, so an agent never waits for a keypress.
listingview catalog listings list --status draft --json | jq '.listings[].title'
The error object is the same one the REST API returns. API: Getting started explains its fields and the retry rules for agents, and every code is on the errors page.
Exit codes
Code | Name | Meaning |
|---|---|---|
0 |
| Success. |
1 |
| Any other failure: not found, a conflict or precondition on your data, or an internal error. Quote the |
2 |
| The request was malformed or out of bounds ( |
3 |
| The API key is missing, invalid, revoked or expired. |
4 |
| The key's scopes or the account's plan don't allow this call, or the feature is off right now. |
5 |
| A budget or rate limit was hit. Wait for the reset ( |
6 |
| A live change on Etsy printed its preview and is waiting for you: run the printed line with |
7 |
| Etsy, Printify, the AI provider or a ListingView dependency failed or is unavailable. Retry later. |
8 |
| A batch finished with some items failed. The CLI prints a per-item table. |
9 |
| Some items have an unknown outcome. Check the shop before retrying, and never resubmit them. |
10 |
|
|
Retries and idempotency
Only retryable errors are retried. The CLI retries only errors the API marks retryable. It waits as long as
retry_afterasks, up to 30 seconds, and makes at most--retriesextra attempts (default 2). If the API asks for a longer wait, the CLI stops with the error instead, so run the command again later.Every change carries an idempotency key. Pass
--idempotency-key <key>to make re-runs safe. For commands that require a key, such asetsy-drafts create,assets uploads beginandcatalog bulk create, the CLI makes one from the command and its input when you don't pass one and prints it on stderr. Running the same command again then returns the first result instead of repeating the work. Any other change gets a new random key on each run, which protects only that run's own retries.No clear answer means exit code 9. If a change ends without a clear answer, the CLI stops with exit code 9 and prints the idempotency key to retry with. Re-run with that key: if the first attempt went through, you get its result back instead of a second change.
Dry runs
With an lv_test_ key, every change is a dry run. The answer shows what would happen, with "dry_run": true, and nothing is written, sent to Etsy or charged. Reads still run for real and use credits as usual.
--dry-run makes sure of it. It needs an lv_test_ key and refuses to run with a live key, so it can never write by mistake:
listingview --profile test etsy-drafts create --stage --shop-id 38123456 --preset-id 1667 --items items.json --dry-run
See Rehearse with a test key in API: Getting started for what a test key checks for real and what comes back unverified.
Upload designs and delivery files
assets upload runs the whole upload protocol from API: Uploads and waits until each file is ready:
listingview assets upload front.png back.png --collection 311 listingview assets upload designs/*.png --json | jq '.[] | select(.ready) | .file_id' listingview assets upload --purpose digital_file printable-planner-2027.pdf
--purposesays what you're uploading:design(the default), ordigital_filefor the files a digital listing delivers to buyers. Delivery files have their own file types and size limit (see API: Uploads).For designs, it checks each file before uploading and refuses anything that isn't PNG, JPEG or WebP. The type is read from the file's bytes, not its name.
Your key is never sent to storage, and upload URLs are never printed.
It waits until every file is ready.
--no-waitreturns right after the upload;--wait-timeout <seconds>changes how long it waits.Running the same command again is safe. Files already in your library show "already in library" and aren't uploaded or counted twice.
Exit codes: 0 every file is ready, 2 a file was refused, quarantined or failed, 8 some files didn't upload (running it again is safe), 10 the wait ran out (the files keep processing).
Etsy drafts
With a Drafting Agent key, turn a preset and your designs into Etsy drafts:
listingview presets list listingview presets get 1667 # in a terminal: the design slots (A, B, …) to fill listingview presets get 1667 --include spec # the whole preset, in the shape presets create accepts listingview etsy-drafts create --shop-id 38123456 --preset-id 1667 --items items.json --wait listingview etsy-drafts jobs status edj_48213 --watch
--itemsreads a JSON array of items from a file, or from stdin with-.Without
--idempotency-key, the key is made from the shop, the preset and the items. Running the same command again, even much later, returns the same job instead of making new drafts. Pass a new--idempotency-keyto make a second batch on purpose.--waitfollows the job until it finishes.--watchalso prints each item as it lands.Exit codes: 0 every item became a draft, 8 some items failed, were skipped or were cancelled, 9 an item's outcome is unknown (check your shop and never resubmit it), 10 the wait ran out (the job keeps running).
Stage a batch for review
Add --stage to save the batch for review in ListingView instead of drafting it at once. Nothing reaches Etsy yet.
listingview etsy-drafts create --stage --shop-id 38123456 --preset-id 1667 --items items.json \ --idempotency-key stage-2026-10-26-batch-01
The answer has the batch's
draft_id, itsrevisionand areview_urlthat opens Saved listings in ListingView.Keep the idempotency key. If the answer is lost, running the same command with the same key returns the same batch while it is open.
Staging takes the copy you already have. Inline AI copy is refused when you stage, so write it first with
listingview ai listing-copy.Then read, edit, submit or discard the batch with
etsy-drafts staged get,update,submitanddelete;etsy-drafts staged listlists your open batches. A submit sends the batch as it is now, including edits made in ListingView, and returns ajob_idthatetsy-drafts jobs statusfollows.
Stage Etsy drafts, review them in ListingView, then submit walks through the whole loop, including edits and conflicts.
Drafts are hidden from shoppers. Publish them with a Publisher key, or with the Publish button in ListingView. For the checks ListingView runs before any draft reaches Etsy, see Using the ListingView API, MCP server & CLI.
Live changes on Etsy
The CLI doesn't publish, push or reprice live listings yet. Publish drafts with the Publish button in ListingView, or through the REST API or MCP with a Publisher key. Publish and reprice live listings covers the confirm step those calls go through.
Related features
API: Getting started: keys, test keys, idempotency, pagination and the error shape
API: Connect AI apps: the same actions as MCP tools in Claude Code or Cursor
API: Uploads: what
assets uploaddoes step by stepBuild presets with the API:
presets get --include specand the building blocksStage Etsy drafts, review them in ListingView, then submit: staged batches from start to finish
Publish and reprice live listings: the Publisher key and the confirm step
API: Limits & budgets: what commands cost and what exit code 5 means for your budget
API reference: every route, generated live from the API
Using the ListingView API, MCP server & CLI: the seller guide to keys, presets and Etsy drafts
listingview runs the ListingView API from your terminal, your scripts and your agents. Every API route is a command. The command list comes from the API itself, so the two always match.
You need an API key first. API: Getting started shows how to make one, and Using the ListingView API, MCP server & CLI explains which kind of key to choose.
Install
You need Node.js 18.3 or newer. The CLI has no other dependencies.
npm install -g @listingview/cli listingview --help
Or run it without installing:
npx @listingview/cli --help
The examples below use listingview. With npx, write npx @listingview/cli instead.
Sign in
For agents, scripts and CI, put the key in the environment:
export LISTINGVIEW_API_KEY=lv_live_… listingview auth status
On your own computer you can save the key instead:
listingview auth login
auth login asks for the key without showing it, or reads it from stdin: printf %s "$KEY" | listingview auth login --key-stdin. It checks the key with GET /api/v1/ping before it saves it (skip that with --no-verify). The key is saved in ~/.listingview/credentials, readable only by you.
Check which key is in use
listingview auth status shows which key is in use, where it came from, which API it talks to and the key's scopes. It prints only the start of the key, never the whole key. Add --offline to skip the call to the API.
When more than one key is around, the first match wins:
--api-key <key>. This works, but the CLI warns you: it ends up in your shell history.--profile <name>LISTINGVIEW_API_KEYThe saved profile named by
LISTINGVIEW_PROFILE, ordefault.
Profiles keep several keys side by side: listingview auth login --profile drafts, then listingview --profile drafts …. Drafting and publishing never share a key, so save a Drafting Agent key and a Publisher key under two profiles. A test key can have its own profile too, for example --profile test.
listingview auth logout removes the saved key from this computer. It doesn't revoke the key. Revoke keys in ListingView under Settings → API Keys.
Environment variables
Variable | Default | What it does |
|---|---|---|
| none | The API key. |
|
| The API origin. |
|
| Which saved profile to use. |
|
| Where the saved keys and the command cache live. |
| none | Use this file as the command list. |
|
| Seconds per request. |
--base-url overrides LISTINGVIEW_BASE_URL. The CLI sends your key only over https://; plain http:// is refused except for localhost.
Commands
The command list comes from the API's describe output. Nobody writes it by hand.
listingview --help # every command listingview etsy-drafts --help # the commands under one word listingview catalog listings list --help # one command's arguments listingview describe --json # the full machine-readable list listingview describe --refresh # fetch the latest list with your key
describe --refresh fetches the live list with your key, saves it, and marks which commands your key can call. Without it, the CLI uses the list it was installed with.
Each command maps to one API route and, where there is one, to an MCP tool. Each line below reads: command · REST route · MCP tool. --help on a command's first word, such as listingview etsy-drafts --help, shows the exact words your installed list has. The API reference documents every route.
Account and discovery
listingview ping·GET /api/v1/ping· no MCP toollistingview describe·GET /api/v1/describe· no MCP toollistingview usage get·GET /api/v1/usage·get_account_usagelistingview usage ai-tokens·GET /api/v1/usage/ai-tokens·get_account_usage
Market research
Every research route is a command under listingview research. Run listingview research --help to list them. Each maps to one of the research tools in API: Connect AI apps.
Your shop
listingview my-shop·GET /api/v1/my-shop·my_shop_performancelistingview my-shop performance·GET /api/v1/my-shop/performance·my_shop_performancelistingview my-shop listing-scores·GET /api/v1/my-shop/listing-scores·my_shop_performance
Listings in ListingView
listingview catalog listings list·GET /api/v1/catalog/listings·list_my_listingslistingview catalog listings get·GET /api/v1/catalog/listings/{listing_id}·get_listinglistingview catalog listings resolve·GET /api/v1/catalog/listings/resolve·get_listinglistingview catalog listings publish-checklist·GET /api/v1/catalog/listings/{listing_id}/publish-checklist·get_listinglistingview catalog listings create·POST /api/v1/catalog/listings·create_local_listinglistingview catalog listings update·PUT /api/v1/catalog/listings/{listing_id}·update_listinglistingview catalog listings images set·PUT /api/v1/catalog/listings/{listing_id}/images·update_listinglistingview catalog listings ai-enhance·POST /api/v1/catalog/listings/{listing_id}/ai-enhance·enhance_listing_with_ailistingview catalog listings lookup·POST /api/v1/catalog/listings/lookup·get_listingwithetsy_listing_ids: up to 100 Etsy listing ids at once, with live state, print-on-demand prices or live inventory
Bulk jobs and AI copy
listingview catalog bulk create·POST /api/v1/catalog/bulk/create·bulk_edit_listings. It requires an idempotency key, so a re-run of the same command returns the same joblistingview catalog bulk edit·POST /api/v1/catalog/bulk/edit·bulk_edit_listingslistingview catalog bulk jobs status·GET /api/v1/catalog/bulk/jobs/{job_id}·get_bulk_job_status. It also reads reprice jobs (lbj_…)listingview ai listing-copy·POST /api/v1/ai/listing-copy·enhance_listing_with_ai
Asset library
listingview assets upload· runs the whole upload: begin, upload, finalize, wait (see API: Uploads).--purpose digital_fileuploads delivery files · no MCP toollistingview assets uploads begin·POST /api/v1/assets/uploads·add_assetslistingview assets uploads finalize·POST /api/v1/assets/uploads/finalize·add_assetslistingview assets images import·POST /api/v1/assets/images/import·add_assetslistingview assets images list·GET /api/v1/assets/images·list_assets.--kind deliverablelists delivery fileslistingview assets files get·GET /api/v1/assets/files·list_assets.--idslooks up to 50 files by id, of any typelistingview assets files update·PATCH /api/v1/assets/files/{file_id}·organize_assetslistingview assets files duplicate·POST /api/v1/assets/files/{file_id}/duplicate·organize_assetslistingview assets files membership·POST /api/v1/assets/files/membership·organize_assetslistingview assets collections·GET /api/v1/assets/collections·list_assetslistingview assets collections create·POST /api/v1/assets/collections·organize_assetslistingview assets collections rename·PATCH /api/v1/assets/collections/{collection_id}·organize_assetslistingview assets collections move·POST /api/v1/assets/collections/{collection_id}/move·organize_assets
Presets
listingview presets list·GET /api/v1/presets·list_presetslistingview presets get·GET /api/v1/presets/{preset_id}·list_presets.--includeadds sections;--include specreturns the full preset as a create bodylistingview presets create·POST /api/v1/presets·manage_presetlistingview presets update·PATCH /api/v1/presets/{preset_id}·manage_presetlistingview presets copy·POST /api/v1/presets/{preset_id}/copy·manage_presetlistingview presets delete·DELETE /api/v1/presets/{preset_id}·delete_preset_or_draftwithkind: "preset"
Preset building blocks
listingview pod-products list·GET /api/v1/pod-products·list_presetswithview: "pod_products"listingview pod-products get·GET /api/v1/pod-products/{product_id}·list_presetswithview: "pod_products"andproduct_idlistingview pod-products providers get·GET /api/v1/pod-products/{product_id}/providers/{provider_id}·list_presetswithview: "pod_products",product_idandprovider_idlistingview etsy-taxonomy properties·GET /api/v1/etsy-taxonomy/{taxonomy_id}/properties·list_presetswithview: "category_attributes"listingview my-shop profiles·GET /api/v1/my-shop/profiles·list_presetswithview: "shop_profiles"listingview mockup-templates list·GET /api/v1/mockup-templates·list_presetswithview: "mockup_templates"
Etsy drafts
listingview etsy-drafts create·POST /api/v1/etsy-drafts·create_etsy_drafts.--stagestages the batch instead (operation: "stage"over MCP)listingview etsy-drafts jobs status·GET /api/v1/etsy-drafts/jobs/{job_id}·get_bulk_job_statuslistingview etsy-drafts jobs list·GET /api/v1/etsy-drafts/jobs·get_bulk_job_statuswithlist: "jobs": your Etsy-draft job historylistingview etsy-drafts staged list·GET /api/v1/etsy-drafts/staged·get_bulk_job_statuswithlist: "staged": your open staged batcheslistingview etsy-drafts staged get·GET /api/v1/etsy-drafts/staged/{draft_id}·get_bulk_job_statuswithdraft_id: one batch as it is nowlistingview etsy-drafts staged update·PATCH /api/v1/etsy-drafts/staged/{draft_id}·create_etsy_draftswithoperation: "update"listingview etsy-drafts staged submit·POST /api/v1/etsy-drafts/staged/{draft_id}/submit·create_etsy_draftswithoperation: "submit"listingview etsy-drafts staged delete·DELETE /api/v1/etsy-drafts/staged/{draft_id}·delete_preset_or_draftwithkind: "staged_batch"listingview catalog listings delete·DELETE /api/v1/catalog/listings/{listing_id}·delete_preset_or_draftwithkind: "etsy_draft": deletes an Etsy draft that ListingView made
Publishing
The CLI doesn't have live-change commands yet: publishing, pushing and repricing aren't in its command list. Use the REST routes or the push_listing_live MCP tool, which Publish and reprice live listings covers.
Arguments
Path parameters come first, in order:
listingview catalog listings get 91234.Everything else is a flag:
--status draftor--status=draft. Booleans take--flagor--no-flag. Repeat a flag to send a list:--ids 88123 --ids 88207.JSON arguments take inline JSON,
@file.json, or-to read stdin.--inputtakes the whole input as JSON. Flags override its keys.
The CLI checks types, required arguments, unknown flags and the API's published size limits before it sends anything. A mistake exits with code 2 and costs nothing.
JSON output for agents
When stdout isn't a terminal (a pipe, a script, an agent), stdout carries exactly one JSON document: the API's answer, or the error object
{"error": {…}}. Notes and warnings go to stderr.In a terminal you get a readable layout.
--jsonor--no-jsonpicks one explicitly.--quiethides notes.--verboselogs each request and its timing to stderr, never the headers, so your key stays out of logs.API commands never prompt, so an agent never waits for a keypress.
listingview catalog listings list --status draft --json | jq '.listings[].title'
The error object is the same one the REST API returns. API: Getting started explains its fields and the retry rules for agents, and every code is on the errors page.
Exit codes
Code | Name | Meaning |
|---|---|---|
0 |
| Success. |
1 |
| Any other failure: not found, a conflict or precondition on your data, or an internal error. Quote the |
2 |
| The request was malformed or out of bounds ( |
3 |
| The API key is missing, invalid, revoked or expired. |
4 |
| The key's scopes or the account's plan don't allow this call, or the feature is off right now. |
5 |
| A budget or rate limit was hit. Wait for the reset ( |
6 |
| A live change on Etsy printed its preview and is waiting for you: run the printed line with |
7 |
| Etsy, Printify, the AI provider or a ListingView dependency failed or is unavailable. Retry later. |
8 |
| A batch finished with some items failed. The CLI prints a per-item table. |
9 |
| Some items have an unknown outcome. Check the shop before retrying, and never resubmit them. |
10 |
|
|
Retries and idempotency
Only retryable errors are retried. The CLI retries only errors the API marks retryable. It waits as long as
retry_afterasks, up to 30 seconds, and makes at most--retriesextra attempts (default 2). If the API asks for a longer wait, the CLI stops with the error instead, so run the command again later.Every change carries an idempotency key. Pass
--idempotency-key <key>to make re-runs safe. For commands that require a key, such asetsy-drafts create,assets uploads beginandcatalog bulk create, the CLI makes one from the command and its input when you don't pass one and prints it on stderr. Running the same command again then returns the first result instead of repeating the work. Any other change gets a new random key on each run, which protects only that run's own retries.No clear answer means exit code 9. If a change ends without a clear answer, the CLI stops with exit code 9 and prints the idempotency key to retry with. Re-run with that key: if the first attempt went through, you get its result back instead of a second change.
Dry runs
With an lv_test_ key, every change is a dry run. The answer shows what would happen, with "dry_run": true, and nothing is written, sent to Etsy or charged. Reads still run for real and use credits as usual.
--dry-run makes sure of it. It needs an lv_test_ key and refuses to run with a live key, so it can never write by mistake:
listingview --profile test etsy-drafts create --stage --shop-id 38123456 --preset-id 1667 --items items.json --dry-run
See Rehearse with a test key in API: Getting started for what a test key checks for real and what comes back unverified.
Upload designs and delivery files
assets upload runs the whole upload protocol from API: Uploads and waits until each file is ready:
listingview assets upload front.png back.png --collection 311 listingview assets upload designs/*.png --json | jq '.[] | select(.ready) | .file_id' listingview assets upload --purpose digital_file printable-planner-2027.pdf
--purposesays what you're uploading:design(the default), ordigital_filefor the files a digital listing delivers to buyers. Delivery files have their own file types and size limit (see API: Uploads).For designs, it checks each file before uploading and refuses anything that isn't PNG, JPEG or WebP. The type is read from the file's bytes, not its name.
Your key is never sent to storage, and upload URLs are never printed.
It waits until every file is ready.
--no-waitreturns right after the upload;--wait-timeout <seconds>changes how long it waits.Running the same command again is safe. Files already in your library show "already in library" and aren't uploaded or counted twice.
Exit codes: 0 every file is ready, 2 a file was refused, quarantined or failed, 8 some files didn't upload (running it again is safe), 10 the wait ran out (the files keep processing).
Etsy drafts
With a Drafting Agent key, turn a preset and your designs into Etsy drafts:
listingview presets list listingview presets get 1667 # in a terminal: the design slots (A, B, …) to fill listingview presets get 1667 --include spec # the whole preset, in the shape presets create accepts listingview etsy-drafts create --shop-id 38123456 --preset-id 1667 --items items.json --wait listingview etsy-drafts jobs status edj_48213 --watch
--itemsreads a JSON array of items from a file, or from stdin with-.Without
--idempotency-key, the key is made from the shop, the preset and the items. Running the same command again, even much later, returns the same job instead of making new drafts. Pass a new--idempotency-keyto make a second batch on purpose.--waitfollows the job until it finishes.--watchalso prints each item as it lands.Exit codes: 0 every item became a draft, 8 some items failed, were skipped or were cancelled, 9 an item's outcome is unknown (check your shop and never resubmit it), 10 the wait ran out (the job keeps running).
Stage a batch for review
Add --stage to save the batch for review in ListingView instead of drafting it at once. Nothing reaches Etsy yet.
listingview etsy-drafts create --stage --shop-id 38123456 --preset-id 1667 --items items.json \ --idempotency-key stage-2026-10-26-batch-01
The answer has the batch's
draft_id, itsrevisionand areview_urlthat opens Saved listings in ListingView.Keep the idempotency key. If the answer is lost, running the same command with the same key returns the same batch while it is open.
Staging takes the copy you already have. Inline AI copy is refused when you stage, so write it first with
listingview ai listing-copy.Then read, edit, submit or discard the batch with
etsy-drafts staged get,update,submitanddelete;etsy-drafts staged listlists your open batches. A submit sends the batch as it is now, including edits made in ListingView, and returns ajob_idthatetsy-drafts jobs statusfollows.
Stage Etsy drafts, review them in ListingView, then submit walks through the whole loop, including edits and conflicts.
Drafts are hidden from shoppers. Publish them with a Publisher key, or with the Publish button in ListingView. For the checks ListingView runs before any draft reaches Etsy, see Using the ListingView API, MCP server & CLI.
Live changes on Etsy
The CLI doesn't publish, push or reprice live listings yet. Publish drafts with the Publish button in ListingView, or through the REST API or MCP with a Publisher key. Publish and reprice live listings covers the confirm step those calls go through.
Related features
API: Getting started: keys, test keys, idempotency, pagination and the error shape
API: Connect AI apps: the same actions as MCP tools in Claude Code or Cursor
API: Uploads: what
assets uploaddoes step by stepBuild presets with the API:
presets get --include specand the building blocksStage Etsy drafts, review them in ListingView, then submit: staged batches from start to finish
Publish and reprice live listings: the Publisher key and the confirm step
API: Limits & budgets: what commands cost and what exit code 5 means for your budget
API reference: every route, generated live from the API
Using the ListingView API, MCP server & CLI: the seller guide to keys, presets and Etsy drafts
Still need help?
Can’t find what you’re looking for? Our team is happy to help.
A.I. Summary