User Workflow
The full operator path: ingest, normalize, transform, publish, and keep inventory in sync.
Ingestion
Three vectors feed the same catalog. Use whichever matches how the product showed up:
- **URL scraper** —
POST /api/import/urlorPOST /api/scrapewith{ "urls": [...], "persist": true }. Best when the storefront exposes JSON-LD. - **Document importer** — CSV, JSON, or PDF via
POST /api/import/document(10MB cap, MIME checks). Google Drive public links are accepted after host checks. - **Browser extension** —
POST /api/extension/ingestwith headerx-toksync-api-key. Use this when you are already on the supplier page and do not want to copy the URL.
Preview before persist when you are learning a new domain. Persist writes products + variants; it does not publish to marketplaces by itself.
AI normalization
After extract, eListSync maps titles, descriptions, currencies, and Size×Color (or similar) matrices into the canonical product + variant schema. Specs such as GTIN, MPN, and weight land in ai_generated_metadata when present.
Normalization is **once per product**, not once per channel. That is the time saving the ROI calculator models (~0.5 minutes per product vs minutes × channels for copy-paste).
If a marketplace needs a different title length or attribute set, the transformer trims or maps fields. You can still edit the canonical record in the catalog; the next publish uses the new values.
Channel transformation
transformForChannel builds the payload the destination API expects:
- Shopify — GraphQL
productCreate/ variant options - Amazon — SP-API listings items JSON for the marketplace id
- eBay — Inventory API item + offer
- WooCommerce — REST product + variations
- Medusa / custom REST — Admin
POST /admin/productswith options and minor-unit prices - TikTok Shop / Walmart — channel-shaped product and inventory bodies
Transformers do not call the source URL. If an attribute is missing, it was missing at ingest or not stored on the variant — fix the catalog, do not patch the transformer per SKU in production.
API publishing
POST /api/products/publish with productIds and destinationAccountIds enqueues one job family per destination bulkhead.
You can publish the same canonical product to several destinations in one action. Listings are tracked separately so a Shopify success and an Amazon rejection can coexist.
Aliases: /api/v1/* maps to the same handlers behind a production gateway.
Inventory sync
After a sale:
- The marketplace sends a webhook (or a poll worker notices the order)
- Idempotency key drops duplicates
- Lua lock decrements canonical (and linked channel) stock
- Sibling channels receive an inventory update so they stop selling a ghost SKU
Seconds, not overnight batch files. If a channel is in an open circuit, we do not silently apply a stale quantity.
When something fails
- **Mapper error** — payload missing a required channel field; fix variants or metadata, republish
- **HTTP 401/403** — re-auth the destination; tokens expire
- **HTTP 429** — backoff on that queue; other channels unaffected
- **Timeout / 5xx** — retries then DLQ; Admin can replay
Open the product's sync log. That row is the source of truth for operators.