SHOP DESKDevelopers
shopdeskbd.com

MCP tools

Every tool the store MCP server offers — scopes, arguments, metering and what comes back — generated from the tool manifest the server’s own registry produces.

How the tools behave

The store MCP server lives at the URL below and authenticates with the same API key, scopes and tenant boundary as the REST API. Setup for Claude Code and other clients is on Build with AI.

https://api.shopdeskbd.com/ext/mcp/v1
  • Your key decides the list. A key sees only the tools all of whose scopes it holds — 36 tools with every scope, none of the write tools with read scopes only.
  • Structured results. Every tool declares an outputSchema and answers with structuredContent, plus the same value as minified JSON text.
  • Concise by default. The order-desk tools answer with the fields needed to act; pass response_format: "detailed" for the full objects.
  • Shopper-written text is data. Notes, addresses, names, emails and checkout answers come back in labelled fields, at most 500 characters, with links, markup and hidden characters removed. The REST API returns them unchanged.
  • Links are downloaded. create_product, create_category, create_brand, add_product_images_from_urls, attach_product_video declare openWorldHint: true: they fetch the image links you pass, through the same checks and limits as the REST API (see Photos by link). Every other tool declares false.
  • Candidates, not guesses.When a name a tool was given matches nothing or several rows — an option name, a parent category — the error object carries candidates beside fields, and nothing is created.
  • Metering.Read tools count against your key’s read limit (the sales and customer summaries as 5 reads); writes against the write limit. See Rate limits.

Read tools

list_products

List products

products:readRead-only1 read per call

A cursor page of products with their variants nested — the variant is the sellable unit (SKU, price). Filters: status, category_id (UUID), search (product name or variant SKU), updated_after (ISO 8601) to sync only what changed. Use get_product instead when you already hold an id. Returns { data: [...], meta: { has_more, next_cursor } }; pass meta.next_cursor as starting_after to fetch the next page.

Idempotency key
not taken
REST twin
GET /ext/v1/products
Returns
data, meta
ArgumentTypeDescription
limitintegerPage size, 1–100 (default 25).
starting_afteruuidCursor: the previous page's meta.next_cursor. Loop until meta.next_cursor is null. Do not combine with ending_before.
ending_beforeuuidCursor for paging backwards: the id of your current first row.
sort"created_at" | "-created_at"-created_at (newest first, the default) or created_at. Use updated_after — not sort — to sync changes.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
status"draft" | "active" | "archived"—
category_iduuidOnly products in this category.
updated_afterstringISO 8601 instant. Only rows changed since then — THE sync filter: it catches rows created earlier but modified since your last poll.
searchstringMatch on product name or variant SKU.

get_product

Get a product

products:readRead-only1 read per call

One product by id (UUID), variants nested. An id outside this key's stores is a plain not-found — indistinguishable from a nonexistent one.

Idempotency key
not taken
REST twin
GET /ext/v1/products/{id}
Returns
id, store_id, name, slug, short_description, description, thumbnail, status, delivery_charge, rating_average, rating_count, brand, categories, images, variants, videos, created_at, updated_at
ArgumentTypeDescription
idrequireduuidThe product id.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.

list_categories

List categories

products:readRead-only1 read per call

A cursor page of product categories (id, name, slug, status). search matches name or slug — how a category name resolves to its id. Category ids feed list_products’ category_id filter. Returns { data: [...], meta: { has_more, next_cursor } }; pass meta.next_cursor as starting_after to fetch the next page.

Idempotency key
not taken
REST twin
GET /ext/v1/categories
Returns
data, meta
ArgumentTypeDescription
limitintegerPage size, 1–100 (default 25).
starting_afteruuidCursor: the previous page's meta.next_cursor. Loop until meta.next_cursor is null. Do not combine with ending_before.
ending_beforeuuidCursor for paging backwards: the id of your current first row.
sort"created_at" | "-created_at"-created_at (newest first, the default) or created_at. Use updated_after — not sort — to sync changes.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
status"active" | "inactive"—
searchstringMatch on name or slug (partial, case-insensitive).

list_brands

List brands

products:readRead-only1 read per call

A cursor page of brands (id, name, slug, status). search matches name or slug. Returns { data: [...], meta: { has_more, next_cursor } }; pass meta.next_cursor as starting_after to fetch the next page.

Idempotency key
not taken
REST twin
GET /ext/v1/brands
Returns
data, meta
ArgumentTypeDescription
limitintegerPage size, 1–100 (default 25).
starting_afteruuidCursor: the previous page's meta.next_cursor. Loop until meta.next_cursor is null. Do not combine with ending_before.
ending_beforeuuidCursor for paging backwards: the id of your current first row.
sort"created_at" | "-created_at"-created_at (newest first, the default) or created_at. Use updated_after — not sort — to sync changes.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
status"active" | "inactive"—
searchstringMatch on name or slug (partial, case-insensitive).

list_orders

List orders

orders:readRead-only1 read per call

A cursor page of orders, compact by default — pass expand: ['customer','items'] for the full objects (keep pages compact when walking many). Filters: status, payment_status, fulfillment_status, channel (channel SLUG from list_channels, not an id), created_after/created_before, search (order number, customer name or phone — any Bangladeshi phone form), customer_id, assignee_id, follow_up_before/follow_up_after (the call-back schedule) and updated_after (ISO 8601) — THE sync filter: it catches an order placed last month but confirmed this morning, which a created_after poll would miss. For a phone lookup or the call list, find_orders and list_orders_needing_attention answer in one call. Returns { data: [...], meta: { has_more, next_cursor } }; pass meta.next_cursor as starting_after to fetch the next page.

Idempotency key
not taken
REST twin
GET /ext/v1/orders
Returns
data, meta
ArgumentTypeDescription
limitintegerPage size, 1–100 (default 25).
starting_afteruuidCursor: the previous page's meta.next_cursor. Loop until meta.next_cursor is null. Do not combine with ending_before.
ending_beforeuuidCursor for paging backwards: the id of your current first row.
sort"created_at" | "-created_at"-created_at (newest first, the default) or created_at. Use updated_after — not sort — to sync changes.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
status"pending" | "follow_up" | "confirmed" | "processing" | "ready_to_ship" | "in_transit" | "delivered" | "returned" | "failed_delivery" | "cancelled" | "hold" | "spam"—
payment_status"unpaid" | "partially_paid" | "paid" | "refunded"—
fulfillment_status"unfulfilled" | "partially_fulfilled" | "fulfilled" | "returned"—
channelstringSales channel slug (e.g. facebook), not its id.
created_afterstringISO 8601 instant.
created_beforestringISO 8601 instant.
updated_afterstringISO 8601 instant. Only rows changed since then — THE sync filter: it catches rows created earlier but modified since your last poll.
searchstringMatch on order number, customer name or phone.
customer_iduuidOnly this customer's orders.
assignee_iduuidOnly orders assigned to this staff member.
follow_up_beforestringISO 8601. Only orders with a call-back due before it.
follow_up_afterstringISO 8601. Only orders with a call-back due after it.
expand"customer" | "items"[]Related objects to include: customer, items.

get_order

Get an order

orders:readRead-only1 read per call

One order by id (UUID). Pass expand: ["customer","items"] for the customer and line items; payment ROWS live behind list_order_payments (a separate scope).

Idempotency key
not taken
REST twin
GET /ext/v1/orders/{id}
Returns
id, store_id, number, source, channel, customer_id, location_id, status, payment_status, fulfillment_status, subtotal, discount_amount, shipping_charge, tax_amount, total_amount, paid_amount, due_amount, refunded_amount, shipping_address, coupon, custom_fields, note, follow_up_at, follow_up_note, assignee, delivered_at, created_at, updated_at, items, customer
ArgumentTypeDescription
idrequireduuidThe order id.
expand"customer" | "items"[]Related objects to include: customer, items.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.

list_order_payments

List an order's payments

payments:readRead-only1 read per call

Every payment recorded against one order, oldest first: settled, pending and refunded rows (refunds are negative amounts with status refunded). Small and unpaginated. Requires the payments:read scope — orders:read alone is not enough.

Idempotency key
not taken
REST twin
GET /ext/v1/orders/{id}/payments
Returns
data
ArgumentTypeDescription
order_idrequireduuidThe order id.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.

list_customers

List customers

customers:readRead-only1 read per call

A cursor page of customer records (name, phone, email, status). search matches name, email or phone (any Bangladeshi phone form). Use get_customer for one record with its addresses, or get_customer_summary for a customer with their order history. Returns { data: [...], meta: { has_more, next_cursor } }; pass meta.next_cursor as starting_after to fetch the next page.

Idempotency key
not taken
REST twin
GET /ext/v1/customers
Returns
data, meta
ArgumentTypeDescription
limitintegerPage size, 1–100 (default 25).
starting_afteruuidCursor: the previous page's meta.next_cursor. Loop until meta.next_cursor is null. Do not combine with ending_before.
ending_beforeuuidCursor for paging backwards: the id of your current first row.
sort"created_at" | "-created_at"-created_at (newest first, the default) or created_at. Use updated_after — not sort — to sync changes.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
searchstringMatch on name, email or phone.

get_customer

Get a customer

customers:readRead-only1 read per call

One customer by id (UUID), addresses included — the detail shape, a superset of the list_customers rows. expand: ["stats"] adds their order history in four numbers (needs orders:read too; omitted without it).

Idempotency key
not taken
REST twin
GET /ext/v1/customers/{id}
Returns
id, store_id, full_name, email, phone, status, type, gender, created_at, updated_at, addresses, stats
ArgumentTypeDescription
idrequireduuidThe customer id.
expand"stats"[]stats: order count, total spent, last order, returns.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.

get_inventory_levels

Get inventory levels

inventory:readRead-only1 read per call

A cursor page of stock levels, one row per variant per location. Filters: warehouse_id, variant_id (both UUIDs), and low_stock: true for only the rows at or below their variant’s low-stock threshold — the reorder question answered server-side. missing_only: true (needs warehouse_id) instead lists the variants that have NEVER had stock set at that location — rows with null id and status: "stock_not_set"; use it to find what is left to stock. Returns { data: [...], meta: { has_more, next_cursor } }; pass meta.next_cursor as starting_after to fetch the next page.

Idempotency key
not taken
REST twin
GET /ext/v1/inventory/levels
Returns
data, meta
ArgumentTypeDescription
limitintegerPage size, 1–100 (default 25).
starting_afteruuidCursor: the previous page's meta.next_cursor. Loop until meta.next_cursor is null. Do not combine with ending_before.
ending_beforeuuidCursor for paging backwards: the id of your current first row.
sort"created_at" | "-created_at"-created_at (newest first, the default) or created_at. Use updated_after — not sort — to sync changes.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
warehouse_iduuidOnly levels at this location.
variant_iduuidOnly levels for this variant.
low_stockbooleanOnly rows at/below the low-stock threshold.
missing_onlybooleanOnly variants with no stock level at warehouse_id yet. Requires warehouse_id; not combinable with low_stock.

list_locations

List locations

locations:readRead-only1 read per call

A cursor page of warehouses and other stock locations. These are COMPANY-scoped: both key types see the same set and store_id does not narrow them. Location ids feed get_inventory_levels’ warehouse_id filter. Returns { data: [...], meta: { has_more, next_cursor } }; pass meta.next_cursor as starting_after to fetch the next page.

Idempotency key
not taken
REST twin
GET /ext/v1/locations
Returns
data, meta
ArgumentTypeDescription
limitintegerPage size, 1–100 (default 25).
starting_afteruuidCursor: the previous page's meta.next_cursor. Loop until meta.next_cursor is null. Do not combine with ending_before.
ending_beforeuuidCursor for paging backwards: the id of your current first row.
sort"created_at" | "-created_at"-created_at (newest first, the default) or created_at. Use updated_after — not sort — to sync changes.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.

list_channels

List sales channels

channels:readRead-only1 read per call

A cursor page of sales channels (id, name, slug) — order attribution metadata. The SLUG is what list_orders’ channel filter takes. Returns { data: [...], meta: { has_more, next_cursor } }; pass meta.next_cursor as starting_after to fetch the next page.

Idempotency key
not taken
REST twin
GET /ext/v1/channels
Returns
data, meta
ArgumentTypeDescription
limitintegerPage size, 1–100 (default 25).
starting_afteruuidCursor: the previous page's meta.next_cursor. Loop until meta.next_cursor is null. Do not combine with ending_before.
ending_beforeuuidCursor for paging backwards: the id of your current first row.
sort"created_at" | "-created_at"-created_at (newest first, the default) or created_at. Use updated_after — not sort — to sync changes.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.

get_store_profile

Get the store profile

store:readRead-only1 read per call

Who this connection works for: the store (name, currency, timezone, contact, languages, advance-payment plans) and this key's access (company, the stores it reaches, its scopes and per-minute limits). A company-wide key must pass store_id to get a store; without it store is null and access.stores lists the stores to choose from.

Idempotency key
not taken
REST twin
GET /ext/v1/store, GET /ext/v1/me
Returns
store, access
ArgumentTypeDescription
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.

get_sales_summary

Get a sales summary

reports:readRead-only5 reads per call

Sales for one store over a window of store-local days: orders, net sales, net revenue and average order value, money received, and the cash on delivery still to collect. The figures run on three clocks, stated in basis: sales count orders DELIVERED in the window, money_received counts payments settled in the window, and cod_outstanding is a balance as of today. Name the window with period or from/to (default: this month so far). compare_to: "previous_period" adds the same figures for the window just before (plans with Advanced Reports only). A company-wide key must pass store_id.

Idempotency key
not taken
response_format
concise or detailed (default concise)
REST twin
GET /ext/v1/reports/sales-summary
Returns
from, to, orders, gross_sales, net_sales, net_revenue, average_order_value, money_received, store_id, time_zone, channel, basis, cod_outstanding, previous_period
ArgumentTypeDescription
period"today" | "yesterday" | "last_7_days" | "last_30_days" | "this_month" | "last_month"A named window on the store calendar.
fromstringFirst day, YYYY-MM-DD (inclusive). Not with period.
tostringLast day, YYYY-MM-DD (inclusive). At most 366 days.
compare_to"previous_period"Adds previous_period.
channelstringOnly this sales channel (its slug, see list_channels). Money received and COD to collect are then null: payments are not split by channel.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
response_format"concise" | "detailed"concise (default): the fields needed to act, names beside ids. detailed: the full objects, as the REST API returns them.

list_low_stock

List low-stock items

inventory:readRead-only1 read per call

What needs restocking: stock rows at or below their low-stock threshold, with product and variant names, on-hand, reserved and available units. Optionally one location (location_id, see list_locations). Pages like every list: pass meta.next_cursor as starting_after for more.

Idempotency key
not taken
response_format
concise or detailed (default concise)
REST twin
GET /ext/v1/inventory/levels
Returns
data, meta
ArgumentTypeDescription
location_iduuidOnly this location (warehouse).
limitintegerPage size, 1–100 (default 25).
starting_afteruuidThe previous page's meta.next_cursor, to fetch the next page. Stop when it is null.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
response_format"concise" | "detailed"concise (default): the fields needed to act, names beside ids. detailed: the full objects, as the REST API returns them.

find_orders

Find orders

orders:readRead-only1 read per call

Finds orders by an order number, a customer phone number or a customer name, newest first. A phone matches in any Bangladeshi form (+8801…, 8801…, 01…). Each row carries the customer, the lines, what is due and the call-back state. Optionally narrowed by status.

Idempotency key
not taken
response_format
concise or detailed (default concise)
REST twin
GET /ext/v1/orders
Returns
data, meta
ArgumentTypeDescription
queryrequiredstringAn order number, a phone number or a customer name.
status"pending" | "follow_up" | "confirmed" | "processing" | "ready_to_ship" | "in_transit" | "delivered" | "returned" | "failed_delivery" | "cancelled" | "hold" | "spam"—
limitintegerPage size, 1–100 (default 25).
starting_afteruuidThe previous page's meta.next_cursor, to fetch the next page. Stop when it is null.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
response_format"concise" | "detailed"concise (default): the fields needed to act, names beside ids. detailed: the full objects, as the REST API returns them.

list_orders_needing_attention

List orders needing attention

orders:readRead-only1 read per call

A work queue, oldest first. unconfirmed: new orders still pending — the confirmation-call list. follow_up_due: orders in follow_up whose call-back time has passed — the same queue the dashboard's overdue follow-ups count. Record each call with record_call_outcome.

Idempotency key
not taken
response_format
concise or detailed (default concise)
REST twin
GET /ext/v1/orders
Returns
data, meta
ArgumentTypeDescription
kindrequired"unconfirmed" | "follow_up_due"Which queue.
limitintegerPage size, 1–100 (default 25).
starting_afteruuidThe previous page's meta.next_cursor, to fetch the next page. Stop when it is null.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
response_format"concise" | "detailed"concise (default): the fields needed to act, names beside ids. detailed: the full objects, as the REST API returns them.

get_customer_summary

Get a customer's history

customers:readorders:readRead-only5 reads per call

One customer and their history: order count, total spent on delivered orders, last order, returns, and their latest 5 orders. Name them by customer_id or by phone (any Bangladeshi form). When a phone matches more than one customer (a company-wide key sees several stores), customer is null and candidates lists them — call again with a customer_id.

Idempotency key
not taken
response_format
concise or detailed (default concise)
REST twin
GET /ext/v1/customers, GET /ext/v1/customers/{id}, GET /ext/v1/orders
Returns
customer, recent_orders, candidates
ArgumentTypeDescription
customer_iduuidThe customer id.
phonestringA Bangladeshi mobile number. Or use customer_id.
store_iduuidRestrict to one store (UUID). Breadth control for company-scoped keys; a store-scoped key may omit it (when sent it must match the key's own store). Narrows the tenant fence, never widens it.
response_format"concise" | "detailed"concise (default): the fields needed to act, names beside ids. detailed: the full objects, as the REST API returns them.

Write tools

create_order

Create an order

orders:writeWrite (adds data; safe to repeat)1 write per call

Places an order through the same engine as the merchant’s own staff: stock is reserved, totals are computed server-side, and any coupon is priced by the real coupon engine (an unusable code fails the order rather than mispricing it). Identify the buyer with customer_id OR an inline customer (find-or-create by phone) — never both. Each line needs variant_id or sku, plus a positive quantity. Returns the created order, the same shape get_order returns.

Idempotency key
required
REST twin
POST /ext/v1/orders
Returns
id, store_id, number, source, channel, customer_id, location_id, status, payment_status, fulfillment_status, subtotal, discount_amount, shipping_charge, tax_amount, total_amount, paid_amount, due_amount, refunded_amount, shipping_address, coupon, custom_fields, note, follow_up_at, follow_up_note, assignee, delivered_at, created_at, updated_at, items, customer
ArgumentTypeDescription
idempotency_keyrequiredstringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Required here.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).
customer_iduuidAn existing customer. Provide this OR customer.
customerobjectFind-or-create by phone. Provide this OR customer_id.
itemsrequiredobject[]The order lines — at least one.
channelstringSales-channel SLUG for attribution (see list_channels); defaults to the store’s manual channel.
location_iduuidWarehouse to allocate stock from; defaults to the company default location.
shipping_addressobjectFree-form address object, stored verbatim.
shipping_chargenumberDelivery charge as your system computed it; default 0.
tax_amountnumber—
coupon_codestring—
notestring—
paymentobjectAn upfront settled payment; omit for an unpaid order and record later payments with record_order_payment.

update_order_status

Update an order’s status

orders:writeWrite (changes existing data)1 write per call

Moves one order to a new status under the SAME strict transition map the merchant’s staff use — an illegal move is refused as INVALID_STATUS_TRANSITION. A delivered order cannot be moved to returned: returns of delivered orders are made in the dashboard. A returned order keeps its stock held (not for sale) until the parcel is received in the dashboard; on a never-delivered order it keeps up to the delivery charge from an advance only when the parcel's pickup is recorded, else everything paid is owed back and no courier charge is booked. returned is refused as CONFLICT while a courier that reports pickups has not reported picking the parcel up; in_transit is refused while the order’s parcel is cancelled (book it again in the dashboard). note lands on the order’s timeline. Use cancel_order for cancellation. Returns the updated order.

Idempotency key
honoured
REST twin
PATCH /ext/v1/orders/{id}/status
Returns
id, store_id, number, source, channel, customer_id, location_id, status, payment_status, fulfillment_status, subtotal, discount_amount, shipping_charge, tax_amount, total_amount, paid_amount, due_amount, refunded_amount, shipping_address, coupon, custom_fields, note, follow_up_at, follow_up_note, assignee, delivered_at, created_at, updated_at, items, customer
ArgumentTypeDescription
idrequireduuidThe order id.
statusrequired"pending" | "follow_up" | "confirmed" | "processing" | "ready_to_ship" | "in_transit" | "delivered" | "returned" | "failed_delivery" | "cancelled" | "hold" | "spam"The target status.
notestring—
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

cancel_order

Cancel an order

orders:writeWrite (changes existing data)1 write per call

Cancels one order — sugar for the cancelled transition, so the same transition map decides whether THIS order can still be cancelled. Reserved stock is released by the same lifecycle rules as the desk. Returns the cancelled order.

Idempotency key
honoured
REST twin
POST /ext/v1/orders/{id}/cancel
Returns
id, store_id, number, source, channel, customer_id, location_id, status, payment_status, fulfillment_status, subtotal, discount_amount, shipping_charge, tax_amount, total_amount, paid_amount, due_amount, refunded_amount, shipping_address, coupon, custom_fields, note, follow_up_at, follow_up_note, assignee, delivered_at, created_at, updated_at, items, customer
ArgumentTypeDescription
idrequireduuidThe order id.
notestringRecorded on the order’s timeline.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

record_order_payment

Record a payment on an order

payments:writeWrite (adds data; safe to repeat)1 write per call

Records a payment that has ALREADY been received — it moves no money itself and contacts no payment provider. The staff payment path verbatim: the amount is capped at the order’s net due (payment_exceeds_due otherwise), and recording the same transaction_id twice in a store is a conflict (duplicate_transaction_id); a method set to require a transaction id refuses a payment without one (transaction_id_required). When a courier has already collected this order at the door, the collection is posted automatically and the order owes nothing — a payment above the due is then refused as cod_already_collected, naming the courier account the cash is sitting in; do not retry it, and record the courier’s remittance instead when it reaches the bank. Requires the payments:write scope — orders:write alone is not enough. Returns the updated order with its payment rollup.

Idempotency key
required
REST twin
POST /ext/v1/orders/{id}/payments
Returns
id, store_id, number, source, channel, customer_id, location_id, status, payment_status, fulfillment_status, subtotal, discount_amount, shipping_charge, tax_amount, total_amount, paid_amount, due_amount, refunded_amount, shipping_address, coupon, custom_fields, note, follow_up_at, follow_up_note, assignee, delivered_at, created_at, updated_at, items, customer
ArgumentTypeDescription
order_idrequireduuidThe order id.
amountrequirednumberSettled amount — above 0.
payment_method_iduuidOne of the store’s ACTIVE payment methods.
transaction_idstringProvider transaction id — unique per store.
idempotency_keyrequiredstringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Required here.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

create_customer

Create a customer

customers:writeWrite (adds data)1 write per call

Creates one customer record. phone (Bangladeshi mobile, stored canonical) and email are each unique per store — a duplicate is a conflict, not a merge. When placing an order for a possibly-new buyer, prefer create_order’s inline customer (find-or-create) over calling this first. Returns the customer, addresses included.

Idempotency key
honoured
REST twin
POST /ext/v1/customers
Returns
id, store_id, full_name, email, phone, status, type, gender, created_at, updated_at, addresses, stats
ArgumentTypeDescription
full_namerequiredstring—
phonestringBangladeshi mobile, any accepted spelling.
emailstring—
status"active" | "inactive" | "blocked"Default active.
gender"male" | "female"—
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

update_customer

Update a customer

customers:writeWrite (changes existing data; safe to repeat)1 write per call

Patches one customer record — only the fields you send change. The same per-store uniqueness rules as create_customer apply to phone and email. Returns the updated customer.

Idempotency key
honoured
REST twin
PATCH /ext/v1/customers/{id}
Returns
id, store_id, full_name, email, phone, status, type, gender, created_at, updated_at, addresses, stats
ArgumentTypeDescription
idrequireduuidThe customer id.
full_namestring—
phonestring—
emailstring—
status"active" | "inactive" | "blocked"—
gender"male" | "female"—
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

adjust_inventory

Adjust stock

inventory:writeWrite (changes existing data; safe to repeat)1 write per call

Sets stock for one variant at one location, with a required audit reason. Name the variant by variant_id or by sku, and the quantity by quantity_change (a delta) or set_on_hand (the resulting total — prefer this when you know the count, and pass expected_on_hand to be refused rather than overwrite a number that moved). quantity_change is never zero, and cannot take on-hand below zero or below reservations. type picks the ledger category: purchase ADDS stock at a required unit_cost, damage must REMOVE stock, return can only ADD stock, default adjustment. A decrease filed as adjustment or damage is booked as a loss on the P&L at the current average cost. Returns the resulting stock level, the same row shape get_inventory_levels pages.

Idempotency key
required
REST twin
POST /ext/v1/inventory/adjustments
Returns
id, store_id, location_id, variant_id, sku, on_hand, reserved, available, low_stock_threshold, is_low_stock, status, location, variant, created_at, updated_at
ArgumentTypeDescription
location_idrequireduuidThe warehouse to adjust.
variant_iduuidThe variant being adjusted. Or resolve by sku.
skustringResolve the variant by SKU instead of id.
quantity_changeintegerSigned units: positive adds, negative removes. Or use set_on_hand to state the resulting total instead.
set_on_handintegerThe absolute on-hand this location should end at — what a stock-take says. The delta is computed under the row lock.
expected_on_handintegerThe on-hand you believe is there; a mismatch refuses the write with CONFLICT instead of applying against a moved number.
type"purchase" | "return" | "adjustment" | "damage"Ledger category; default adjustment.
reasonrequiredstringStored on the ledger entry. Required — always.
unit_costnumberPer-unit cost. REQUIRED for purchase and refused on any other type; write-only, never appears in any response.
low_stock_thresholdintegerOptionally update the level’s low-stock threshold.
idempotency_keyrequiredstringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Required here.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

create_product

Create a product

products:writeWrite (adds data)1 write per callDownloads the links you send

Creates one product with at least one variant (the sellable unit: SKU + price) — optionally with its photos and each variant’s options, in one call. images: up to 10 https links, which Shopdesk downloads, checks and stores before answering; one link that cannot be used fails the whole call and nothing is created. A variant’s options name an attribute and a value by name (any case), slug or id, e.g. [{"attribute":"Colour","value":"Red"}]. Nothing is created from a name: an unknown one fails the call with candidates (the store’s variant attributes, or that attribute’s values) — add what is missing with create_attribute. image_index points a variant at a photo by its position in images. slug auto-generates from the name and auto-suffixes when taken. description is stored as sanitized HTML. Stock is NOT set here — new stock enters through adjust_inventory, where the ledger rules live. Returns the product, the same shape get_product returns.

Idempotency key
honoured
REST twin
GET /ext/v1/attributes, POST /ext/v1/products
Returns
id, store_id, name, slug, short_description, description, thumbnail, status, delivery_charge, rating_average, rating_count, brand, categories, images, variants, videos, created_at, updated_at
ArgumentTypeDescription
namerequiredstring—
variantsrequiredobject[]At least one variant.
slugstring—
brand_iduuid—
short_descriptionstring—
descriptionstringRich description; sanitized server-side.
status"draft" | "active" | "archived"Default draft.
delivery_chargenumberPer-product override: 0 = free delivery, N = flat charge; omit for the standard shipping rules.
categoriesobject[]—
imagesobject[]The gallery, in display order, by https link. Add more later with add_product_images_from_urls.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

update_product

Update a product

products:writeWrite (changes existing data)1 write per call

Patches one product — only the fields you send change, with two REPLACE semantics to know: categories (when present) replaces the whole link set, and variants (when present) reconciles the FULL variant set — entries with an id are patched, entries without one are created, and existing variants missing from the list are REMOVED (refused when they carry stock history). A NEW variant takes options by name, like create_product; an existing one keeps its options. Photos are not edited here — use add_product_images_from_urls, and update_variant for a variant’s photo. brand_id: null detaches the brand; delivery_charge: null returns to the standard shipping rules. Returns the updated product.

Idempotency key
honoured
REST twin
GET /ext/v1/attributes, PATCH /ext/v1/products/{id}
Returns
id, store_id, name, slug, short_description, description, thumbnail, status, delivery_charge, rating_average, rating_count, brand, categories, images, variants, videos, created_at, updated_at
ArgumentTypeDescription
idrequireduuidThe product id.
namestring—
slugstring—
brand_iduuid | nullSet null to detach the brand.
short_descriptionstring—
descriptionstring—
status"draft" | "active" | "archived"—
delivery_chargenumber | nullSet null to return to the standard shipping rules.
categoriesobject[]When present, REPLACES the category links.
variantsobject[]When present, reconciles the FULL variant set — see the tool description before sending a partial list.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

archive_product

Archive a product

products:writeWrite (changes existing data; safe to repeat)1 write per call

Archives one product — it leaves the sellable catalog but its history stays. There is no delete on this surface; archiving is the end state. Returns { id, archived }.

Idempotency key
honoured
REST twin
POST /ext/v1/products/{id}/archive
Returns
id, archived
ArgumentTypeDescription
idrequireduuidThe product id.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

update_order_details

Update an order’s note or call-back

orders:writeWrite (changes existing data; safe to repeat)1 write per call

Sets an order’s note and call-back (follow_up_at, follow_up_note) — nothing that changes money or stock, legal in any status. Only the fields you send change; null clears one. note REPLACES the whole note: text these tools show is shortened to 500 characters, so never rebuild a note from a value ending in "…". Returns the updated order.

Idempotency key
honoured
REST twin
PATCH /ext/v1/orders/{id}
Returns
id, store_id, number, source, channel, customer_id, location_id, status, payment_status, fulfillment_status, subtotal, discount_amount, shipping_charge, tax_amount, total_amount, paid_amount, due_amount, refunded_amount, shipping_address, coupon, custom_fields, note, follow_up_at, follow_up_note, assignee, delivered_at, created_at, updated_at, items, customer
ArgumentTypeDescription
order_idrequireduuidThe order id (UUID). Find it with find_orders.
notestring | nullThe order note. null clears it.
follow_up_atstring | nullWhen to call back (ISO 8601). null clears it.
follow_up_notestring | nullWhy the call-back is needed. null clears it.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

record_call_outcome

Record a call outcome

orders:writeWrite (changes existing data)1 write per call

Records the result of a confirmation call on one order, using the same status rules as the dashboard. confirmed moves it to confirmed; cancelled cancels it (stock is released). call_back (needs call_back_at) and no_answer (call_back_at optional) move it to follow_up — the dashboard’s call-back queue — and set the call-back time and note as the reason. note also goes on the order timeline with a status change. A status the order cannot move to is refused before anything changes. Repeating the same outcome changes nothing more. Returns the steps taken and the order.

Idempotency key
honoured
response_format
concise or detailed (default concise)
REST twin
GET /ext/v1/orders/{id}, PATCH /ext/v1/orders/{id}/status, POST /ext/v1/orders/{id}/cancel, PATCH /ext/v1/orders/{id}
Returns
outcome, steps, order
ArgumentTypeDescription
order_idrequireduuidThe order id (UUID). Find it with find_orders.
outcomerequired"confirmed" | "cancelled" | "call_back" | "no_answer"What the call decided.
notestringWhat was said, in a sentence.
call_back_atstringWhen to call again (ISO 8601). Required for call_back; not allowed with confirmed or cancelled.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).
response_format"concise" | "detailed"concise (default): the fields needed to act, names beside ids. detailed: the full objects, as the REST API returns them.

create_attribute

Create an attribute (or add its missing values)

catalog:writeproducts:readWrite (adds data; safe to repeat)1 write per call

Makes sure an attribute (Colour, Size) exists with the values you list, and returns it with all its values. If the store already has an attribute with this name and type (or this slug), only the values it lacks are added, compared ignoring case — nothing is renamed, changed or removed, so calling it twice adds nothing the second time; added values go after the existing ones unless position places them. Otherwise the attribute is created with the values in order. type: variant (default) for options that define variants (what create_product options name), specification for details that only describe a product. input_type: "color" lets values carry swatch_hex. Returns { attribute, created, added_values }.

Idempotency key
honoured
REST twin
GET /ext/v1/attributes, POST /ext/v1/attributes, POST /ext/v1/attributes/{id}/values, GET /ext/v1/attributes/{id}
Returns
attribute, created, added_values
ArgumentTypeDescription
namerequiredstringe.g. Colour.
slugstringLook up (and create) by this slug instead of the name: lowercase letters, digits and single hyphens.
type"variant" | "specification"variant (default) or specification.
input_type"text" | "color" | "image"On create only: text (default), color (values take swatch_hex) or image.
is_filterablebooleanOn create only: offer it as a storefront filter.
is_requiredbooleanOn create only.
valuesobject[]The values it must have, in order. Each value once.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

create_category

Create a category

catalog:writeproducts:readWrite (adds data)1 write per callDownloads the links you send

Creates one category, top-level or under parent — the parent category’s name, slug or id. A parent name that matches no category, or several, fails with candidates; send the slug or id. Images come by https link (image_url for listings, banner_url for the category page): Shopdesk downloads and checks them before answering, and a link that cannot be used fails the call with nothing created. Each call creates a new category — check list_categories first. slug derives from the name and is suffixed when taken. Returns the category.

Idempotency key
honoured
REST twin
GET /ext/v1/categories, POST /ext/v1/categories
Returns
id, store_id, parent_id, name, slug, image, banner_image, description, seo, status, position, created_at, updated_at
ArgumentTypeDescription
namerequiredstring—
parentstringThe parent category: name (any case), slug or id. Omit for a top-level category.
slugstring—
descriptionstring—
status"active" | "inactive"Default active.
positionintegerSort order among siblings, lowest first.
seoobject—
image_urlstringListing image, by https link. Shopdesk downloads it, checks it is a PNG, JPEG, WebP or GIF (at most 10 MB) and stores its own copy.
banner_urlstringCategory-page banner, by https link. Shopdesk downloads it, checks it is a PNG, JPEG, WebP or GIF (at most 10 MB) and stores its own copy.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

create_brand

Create a brand

catalog:writeWrite (adds data)1 write per callDownloads the links you send

Creates one brand, with an optional logo (logo_url) and banner (banner_url) by https link: Shopdesk downloads and checks them before answering, and a link that cannot be used fails the call with nothing created. Each call creates a new brand — check list_brands first. slug derives from the name and is suffixed when taken. Returns the brand.

Idempotency key
honoured
REST twin
POST /ext/v1/brands
Returns
id, store_id, name, slug, logo, banner_image, description, seo, status, created_at, updated_at
ArgumentTypeDescription
namerequiredstring—
slugstring—
descriptionstring—
status"active" | "inactive"Default active.
seoobject—
logo_urlstringBrand logo, by https link. Shopdesk downloads it, checks it is a PNG, JPEG, WebP or GIF (at most 10 MB) and stores its own copy.
banner_urlstringBrand-page banner, by https link. Shopdesk downloads it, checks it is a PNG, JPEG, WebP or GIF (at most 10 MB) and stores its own copy.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

add_product_images_from_urls

Add product photos from links

products:writeWrite (adds data)1 write per callDownloads the links you send

Adds up to 10 photos to one product’s gallery from https links, in one change. Shopdesk downloads each link, checks it is a PNG, JPEG, WebP or GIF (at most 10 MB and 8000 px) and stores its own copy; the link is not kept. All or nothing: one link that cannot be used fails the call, naming images[i].source_url, and no photo is added. Photos are appended unless position says otherwise; is_thumbnail: true makes one the product thumbnail. A gallery holds at most 30 photos. With an idempotency_key, a retry answers without downloading again. Returns { data }: the new photos in the order sent, with their ids.

Idempotency key
honoured
REST twin
POST /ext/v1/products/{id}/images
Returns
data
ArgumentTypeDescription
product_idrequireduuidThe product id.
imagesrequiredobject[]The photos, in order.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

update_variant

Update a variant

products:writeWrite (changes existing data; safe to repeat)1 write per call

Edits one variant: price, discount_price, sku, barcode, weight and its photo (image_id, one of the product’s photos from get_product), with the dashboard’s rules — a sale price must be below the price, and the SKU is locked once the variant has stock or orders. Name the variant by id, SKU or barcode. Only the fields you send change; null clears discount_price, barcode, weight or image_id. Options and cost are not edited here. Returns the variant.

Idempotency key
honoured
REST twin
PATCH /ext/v1/variants/{identifier}
Returns
id, store_id, product_id, sku, barcode, name, price, discount_price, weight, dimensions, low_stock_threshold, status, image, options, created_at, updated_at
ArgumentTypeDescription
variantrequiredstringThe variant’s id, SKU or barcode.
pricenumber—
discount_pricenumber | nullSale price, below the price. null removes it.
skustring—
barcodestring | nullnull removes it.
weightnumber | nullShipping weight in kg. null removes it.
image_iduuid | nullOne of the product’s photo ids. null falls back to the product thumbnail.
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

attach_product_video

Attach a video to a product

videos:writeWrite (adds data)1 write per callDownloads the links you send

Puts a video on a product. With video_url (an https link to an H.264 MP4 file — not a YouTube or other player page) Shopdesk imports the file in the background and places it at once: it shows on the product once verified, and video.status / placement.status say where it is (poll with get_product, whose videos[] lists ready videos). idempotency_key is required with video_url. With video_id (a video this key uploaded) it only places it. With neither it changes nothing and returns upload_steps, the calls a script makes to upload a file. option shows the video only for one option value of the product’s active variants, by name (e.g. { "attribute": "Colour", "value": "Red" } — this reads the product, so the key needs products:read too; a name the product does not use answers with candidates), or option_value_id by id. If an import started but the video could not then be placed, the error names the imported video id: call again with that video_id. gallery_slot is how many photos come before it (default 1, after the main photo). Placing a video the product already shows moves it. Returns { video, placement, upload_steps }.

Idempotency key
honoured
REST twin
GET /ext/v1/products/{id}, POST /ext/v1/videos/import, POST /ext/v1/products/{id}/videos
Returns
video, placement, upload_steps
ArgumentTypeDescription
product_idrequireduuidThe product id.
video_urlstringAn https link to the MP4 file itself, at most 200 MB. Shopdesk downloads it and keeps its own copy (the link is not kept).
video_iduuidA video this key already uploaded or imported.
optionobjectShow the video only for this option value of the product’s variants, by name (needs products:read). Omit for every variant.
option_value_iduuidThe same by id: a variant’s options[].value_id from get_product.
titlestringIts accessible name; defaults to the product name.
gallery_slotintegerPhotos before the video: 0 = first, default 1.
sort_orderintegerOrder among the product's videos (default 0).
idempotency_keystringA value unique to this LOGICAL operation (a UUID is ideal) — reuse the SAME value when retrying it, so a lost response can never double-run the write. Optional here, but recommended for automated callers.
store_iduuidWhich store to write into (UUID). REQUIRED for a company-scoped key; a store-scoped key may omit it (when sent it must match the key's own store).

REST operations with no tool

Every REST operation has a tool or a written reason for having none:

  • GET /ext/v1/variants/{identifier} — get_product returns every variant of the product nested, and list_products searches by variant SKU; a per-variant lookup would be a second tool answering the same question.
  • GET /ext/v1/categories/{id} — list_categories returns the same rows; one category is never worth a tool of its own.
  • GET /ext/v1/brands/{id} — list_brands returns the same rows; one brand is never worth a tool of its own.
  • GET /ext/v1/locations/{id} — list_locations returns the same rows; a store has a handful of locations.
  • GET /ext/v1/inventory/movements — The stock ledger is sync data for ERPs and accounting, read over REST; get_inventory_levels answers the conversational question (how much is there).
  • POST /ext/v1/products/{id}/images/reorder — Reordering photos is install-time catalog work (§5.1: photo delete, reorder and alt-text edits stay REST-only), and it restates the whole gallery, which a model gets wrong too easily.
  • PATCH /ext/v1/products/{id}/images/{imageId} — Photo alt-text, order and main-photo edits are install-time catalog work (§5.1); add_product_images_from_urls sets alt text, position and the main photo when it adds a photo.
  • DELETE /ext/v1/products/{id}/images/{imageId} — A permanent photo delete is kept to REST (§5.1) so a conversation cannot remove catalog media.
  • PATCH /ext/v1/attributes/{id} — Renaming an attribute or changing its type or flags is install-time catalog work; create_attribute never renames or removes anything.
  • PATCH /ext/v1/attributes/{id}/values/{valueId} — Renaming a value relabels every variant that shows it — catalog correction work, kept to REST and the dashboard.
  • PATCH /ext/v1/categories/{id} — Category edits (moves, renames, image swaps) are install-time catalog work; create_category covers the conversational case.
  • PATCH /ext/v1/brands/{id} — Brand edits (renames, logo swaps) are install-time catalog work; create_brand covers the conversational case.
  • POST /ext/v1/videos — Starting an upload session is binary work for a script or the SDK: the caller then PUTs file parts to storage, which a model cannot do (§5.1). attach_product_video takes a finished upload’s video_id.
  • POST /ext/v1/videos/{id}/part-urls — Part URLs exist only to PUT file bytes to storage — binary is not tool-shaped (§5.1).
  • POST /ext/v1/videos/{id}/complete — Completing an upload follows the byte transfer a script makes; it is part of the same upload session (§5.1).
  • GET /ext/v1/videos — Upload-session status for the script doing the upload (§5.1); get_product shows a product’s ready videos.
  • GET /ext/v1/videos/{id} — Upload-session status for the script doing the upload (§5.1); get_product shows a product’s ready videos.
  • DELETE /ext/v1/videos/{id} — Video deletes are kept to REST (§5.1: video posters and deletes), so a conversation cannot remove catalog media.
  • POST /ext/v1/videos/{id}/poster — Video covers are kept to REST (§5.1: video posters and deletes): an uploaded cover is binary, and a product page falls back to the product thumbnail without one.
  • DELETE /ext/v1/products/{id}/videos/{videoId} — Taking a video off a product is a media delete, kept to REST (§5.1: video posters and deletes) so a conversation cannot remove catalog media; attach_product_video only adds or moves a video.
  • GET /ext/v1/reports/top-products — EXPANSION_PLAN §5.1 lists no tool for the ranking: get_sales_summary answers the conversational sales question, and the tool budget is held for the order desk. A BI sync reads the ranking over REST; adding a tool later means moving this line to MCP_REST_TWIN.