Skip to content

JavaScript SDK

Mehrdad Pajuhaan edited this page Oct 23, 2026 · 1 revision

JavaScript SDK

This page is the reference for window.$backoffice, the request layer of @selldone/sdk-backoffice. It lists every namespace and method registered by BackofficeSDK.Setup(), the REST endpoint behind each method, and the main response fields. All endpoints are relative to the selldone-api base URL (https://api.selldone.com). If you have not set up the SDK yet, start with Getting Started.

How the SDK is organized

Global Created by What it is
window.API BackofficeSDK.Setup() Catalog of URL builders (apis/API.ts). Each method returns a full URL, for example window.API.GET_ALL_MY_PRODUCTS(shop_id). Doc comments list the HTTP method, auth, token scope and errors.
window.ADDRESS_API, window.ARTICLE_API BackofficeSDK.Setup() Aliases of window.API.
window.$backoffice BackofficeSDK.Setup() Typed request wrappers grouped by domain (this page).
window.axios BackofficeSDK.Setup() The Axios instance used by all wrappers. Add your Authorization header here.

Conventions used by the wrappers:

  • Lists take (id, offset, limit, options?). options are sent as query parameters together with offset and limit, and the response includes total.
  • Promises resolve with the response body. They reject with the error body ({ error: true, error_msg, code }) when the API reports an error, or with an Axios error for network and HTTP failures.
  • Types: each request file exports a namespace with IResponse (and IParams when there are options), for example api.shop.products.get.IParams.

Caching, cancellation and optimization

Every namespace object extends APIAbstract from Selldone Core and exposes these chainable helpers:

Helper Effect
promise.cache(callback) On GET requests, calls callback immediately with the last cached response for the same URL and query (if any), and caches the fresh response when it arrives. Call it before .then().
.optimize(seconds = 60) GET requests resolve with the cached response, without calling the server, if it is younger than seconds.
.force() Clears the optimize() setting so the next GET always reaches the server.
.cancellation(enabled = true) A new GET request to the same URL cancels the pending one. A canceled request rejects with undefined.

Responses are kept in an in-memory cache of up to 100 entries, and only for requests where .cache() was chained. optimize() and cancellation() set state on the namespace object, so they also apply to later calls on that object until you change them.

window.$backoffice.category
  .cancellation()
  .list(SHOP_ID, 0, 50, { search: "shoes", children: true })
  .cache(({ categories }) => showCategories(categories))
  .then(({ categories, total }) => showCategories(categories, total))
  .catch((error) => error && console.error(error));

auth

Method Endpoint Response
logout() POST /logout-selldone { success }

user

Method Endpoint Response
preferences.save(preferences) PUT /preferences { preferences }

preferences is a User.Preferences object from Selldone Core.

page

Method Endpoint Response
list(shop_id, offset, limit, options?) GET /shops/{shop_id}/pages { pages, total }
getPageAugment(shop_id, page_id, current_augment?) GET /shops/{shop_id}/pages/{page_id}/augment { augment }

list options: contain (force a page ID into the result), search, cluster_id, sortBy, sortDesc, compact, published_only.

getPageAugment returns the augment items of a page ({ key, value, type: "image" | "text" }). If you pass current_augment, the SDK merges it with the server structure.

product

Method Endpoint Response
list(shop_id, offset, limit, options?) GET /shops/{shop_id}/products/all-admin { folders, products, parent_folders, total, tax_profile?, valuation?, time_filter? }
getInfo(shop_id, product_id, offset, limit, options?) GET /shops/{shop_id}/products/{product_id}/admin { product, product_data, orderQue }
setQuantity(shop_id, product_id, quantity) POST /shops/{shop_id}/products/{product_id}/quantity { success, quantity }
changeCategory(shop_id, product_id, category_id, bundle?) PUT /shops/{shop_id}/products/{product_id}/edit/category { success, count }
  • list options: statuses, types, sort, available, set ("default" or "spec"), dir, with_product_variants, with_parent, search, vendor, products_only, with_total, show_deletes, show_vendors, with_category. The REST endpoint accepts more filters; see Fetch Products List.
  • getInfo option: with_trashed. The product object includes product_variants, images, category, vendor, subscription_prices, extra_pricings, articles and more.
  • changeCategory: pass null as category_id to move the product to the root. bundle is an optional array of product IDs to move together; count is the number of products changed.

product.importer

Method Endpoint Response
send(shop_id, dataset, keep_image_urls = true) POST /shops/{shop_id}/import/products { success, success_count, fail_count, errors }
info(shop_id) GET /shops/{shop_id}/importing { importing, "images-que" }
que.products(shop_id, offset, limit, options?) GET /shops/{shop_id}/import/products { products, total }
que.removeProduct(shop_id, item_id) DELETE /shops/{shop_id}/import/products/{item_id} { success, id }
que.images(shop_id, offset, limit, options?) GET /shops/{shop_id}/import/images { images, total }
que.removeImage(shop_id, item_id) DELETE /shops/{shop_id}/import/images/{item_id} { success, id }
que.syncImage(shop_id, item_id) PUT /shops/{shop_id}/import/images/{item_id}/try { success, id?, item? }

send expects a spreadsheet-style dataset: the first row must be an array of header strings, otherwise the SDK throws before sending. Supported columns include Product ID, Variant ID, Title, Type, Price, Currency, Status, Quantity, SKU, MPN, GTIN, Category, Brand, Image, Images, V_Color, V_Style, V_Volume, V_Weight, V_Pack, V_Type, Limit Min, Limit Max, and tiered pricing pairs Qty 1/Price 1 through Qty 10/Price 10 (see api.product.importer.post.IProduct for the full list). The queue options are sortBy, sortDesc and search. syncImage returns id when the queued image is resolved, or item with its updated status.

const dataset = [
  ["Title", "Type", "Price", "Currency", "Status", "Quantity", "SKU"],
  ["Eco Yoga Mat", "PHYSICAL", 19.95, "USD", "Open", 50, "YOGA-ECO"],
];
const { success_count, fail_count, errors } =
  await window.$backoffice.product.importer.send(SHOP_ID, dataset);

Other product sub-namespaces

Method Endpoint Response
tags.set(shop_id, product_id, tags) POST /shops/{shop_id}/products/{product_id}/tags { success, tags }
variants.remove(shop_id, product_id, variant_id) DELETE /shops/{shop_id}/products/{product_id}/variants/{variant_id}/delete { success, variants, quantity, variant_id }
variants.restore(shop_id, product_id, variant_id) POST /shops/{shop_id}/products/{product_id}/variants/{variant_id}/restore { success, variants, quantity, product_variant }
ar.remove(shop_id, product_id, file_type, variant_id = null) DELETE /shops/{shop_id}/products/{product_id}/ar/{file_type}[/{variant_id}] { success, ar }
vendor.list(shop_id, product_id, offset, limit, options?) GET /shops/{shop_id}/products/{product_id}/vendors { vendor_products, total }
subscriptionPricing.list(shop_id, offset, limit, options?) GET /shops/{shop_id}/subscription-prices { subscription_prices, total }
  • ar.remove: file_type is "src" or "ios".
  • vendor.list options: sortBy, sortDesc, search, vendor_id. See Vendor Products List.
  • subscriptionPricing.list options: sortBy, sortDesc, search, compact, product_id, with_product.

category

Method Endpoint Response
list(shop_id, offset, limit, options?) GET /shops/{shop_id}/categories { categories, total, parent_folders }

Options: contain, updated_at (ISO 8601), sortBy (id, name, title, star, icon, parent_id, visits, products, categories, vendor_id, page_id, created_at, updated_at), sortDesc, search, children, parent, page.

blog

Method Endpoint Response
list(shop_id, offset, limit, options?) GET /shops/{shop_id}/blogs { articles, total }
categories.list(shop_id, offset, limit, options?) GET /shops/{shop_id}/blog/categories { categories, total }
categories.add(shop_id, params?) POST /shops/{shop_id}/blog/categories { success, category }
categories.edit(shop_id, category_id, params?) PUT /shops/{shop_id}/blog/categories/{category_id} { success, category }
categories.remove(shop_id, category_id) DELETE /shops/{shop_id}/blog/categories/{category_id} { success, id }

list options: search, cluster_id, sortBy, sortDesc. Category params: category, description, star.

vendor

Method Endpoint Response
list(shop_id, offset, limit, options?) GET /shops/{shop_id}/vendors { vendors, total }

Options: contain, search, active_only, compact. See Get Vendors List.

agency

Method Endpoint Response
getInfo(agency_id) GET /agencies/{agency_id} { agency }
shops.list(agency_id, offset, limit, options?) GET /agencies/{agency_id}/shops { shops, total }
shops.add(agency_id, title, currency, plan, language) POST /agencies/{agency_id}/shops { success, shop }
clients.list(agency_id, offset, limit, options?) GET /agencies/{agency_id}/clients { clients, total }
wallet.createWallet(agency_id, currency) POST /agencies/{agency_id}/create-wallet { success, wallet }
wallet.setAccount(agency_id, account_id) POST /agencies/{agency_id}/account { success, agency, account }
wallet.charge(agency_id, currency, amount) POST /agencies/{agency_id}/charge-wallet { success, wallet }
wallet.claimGift(agency_id, code) POST /agencies/{agency_id}/claim-gift { success, wallet, amount, currency }
  • List options: search, plan, sortBy, sortDesc.
  • createWallet: choose the currency carefully; it cannot be changed later.
  • charge moves funds from the connected account to the agency wallet. claimGift charges the wallet with an available free credit code.

article

Method Endpoint Response
tags.getTags(shop_id) GET /shops/{shop_id}/articles/tags { tags }
tags.setArticleTags(shop_id, article_id, tags) POST /shops/{shop_id}/articles/tags/{article_id} { tags }
tags.updateTag(shop_id, old_tag, new_tag) PUT /shops/{shop_id}/articles/tags { success }

tags.updateTag builds its URL with window.XAPI (the Storefront SDK URL catalog), so it requires the Storefront SDK to be set up in the same page.

logistic

Method Endpoint Response
profile.list(shop_id, offset, limit, options?) GET /shops/{shop_id}/logistic-profiles { profiles, total }
profile.get(shop_id, profile_id, options?) GET /shops/{shop_id}/logistic-profiles/{profile_id} { profile, articles }

list options: sortBy, sortDesc, search, contain, compact, type (a LogisticProfileType key).

map

Method Endpoint Response
tag.list(shop_id, offset, limit, options?) GET /shops/{shop_id}/map/tags { map_tags, total }

Options: sortBy, sortDesc, search, contain, compact.

affiliate

Method Endpoint Response
pos.list(affiliate_id, offset, limit, options?) GET /affiliates/{affiliate_id}/products { folders, products, parent_folders, total }

Accepts the same options as product.list.

finance

Method Endpoint Response
exchange.list() GET /exchange/rates An object of exchange rates keyed by currency code

Calling endpoints that have no wrapper

window.$backoffice covers the most common operations. For any other endpoint, build the URL with window.API and call it with window.axios:

// PUT /shops/{shop_id}/products/{product_id}/edit
const { data } = await window.axios.put(
  window.API.PUT_EDIT_PRODUCT(SHOP_ID, PRODUCT_ID),
  { sku: "YOGA-2024-ECO" },
);
if (data.error) throw new Error(data.error_msg);

Open apis/API.ts (or the generated catalog ai-guideline/_generated/api-url-builders.md) to find the builder, the HTTP method and the required token scope of an endpoint.

Next steps

Clone this wiki locally