## Overview

**Sync Studio** connects external e-commerce platforms and marketplaces to your **native catalog** in
Conversa Labs. You set up **sync sources** that can:

- **Import (inbound)** — pull the products from the external platform into the native catalog;
- **Publish (outbound)** — push products from the native catalog to the external platform;
- **Keep both ways** — combine import and publish on the same source.

Sync Studio is different from two nearby features:

- **WhatsApp Business Catalog (Meta) sync** links the native catalog to the Meta catalog so you can send
  products on WhatsApp — it has its own article.
- The **e-commerce lifecycle** handles **sale events** (abandoned cart, pending PIX, approved purchase,
  refund) that turn into cards in the conversation — it also has its own article.

Sync Studio is about the **product catalog**: what is for sale, with name, price, and images.

## Prerequisites

- The **Catalog & Commerce** module enabled for your account.
- **Administrator** permission to manage sync sources.
- An account and **access credentials** on the external platform (token, app keys, or authorization,
  depending on the connector).
- Recommended: a native catalog already organized into categories before publishing products outward.

## Step by step

1. In the **Catalog** area, open **Sync Studio** (sync sources) and click to create a **new source**.
2. Pick the **connector/preset**: Generic source, Shopify, WooCommerce, Magento, PrestaShop, Medusa,
   Mercado Livre, Nuvemshop, Hotmart, Kiwify, or OLX.
3. Set the **direction**: **Inbound** (import), **Outbound** (publish), or **Both ways**.
4. **Authenticate** the source according to the connector:
   - **Mercado Livre** — click **Authorize**; you are taken to the platform's login screen and, once you
     approve, returned to the fixed address `/catalog_oauth/callback`. Tokens are stored encrypted.
   - **Hotmart / Kiwify** — provide `client_id` and `client_secret` (plus `account_id` for Kiwify).
     Hotmart's `basic_token` remains accepted for legacy sources but is derived automatically when it
     is absent. Kiwify receives the credentials as a form and generates the token.
   - **Generic source, Shopify, WooCommerce, Magento, PrestaShop, Medusa** — choose Bearer, header,
     **Basic** (username and password), or **URL query parameter** authentication, then set the mapping.
   - **Nuvemshop** — paste the store token and the `store_id`.
5. Use **Test connection** for a saved Hotmart or Kiwify source. For a Generic source, use the **live
   preview** before saving: it makes the same call as sync and shows the response, actual parsed format,
   detected fields, mapping suggestions, and the first mapped record.
6. Save and click **Sync now** to run the first import (or **Publish now** for an outbound source).
7. Follow the paginated and filterable **run history** to see every sync, with times in the account
   timezone, direction, and result (items read, created, updated, skipped, or failed). The source list
   also shows safe counters and the latest error without exposing credentials. You can export the
   filtered history or explicitly selected runs as CSV; a partial export keeps failed run IDs visible.

## Settings & options

- **Connector / preset (source_type)** — the origin/destination platform.
- **Direction** — inbound, outbound, or both ways.
- **Credentials** — stored **encrypted**, never shown back, and never written to logs.
- **Sync interval** — how often the source is synced automatically (on top of manual, on-demand syncs).
- **Source state** — a disabled source remains editable, but it does not accept webhooks or execute
  **Sync now**, **Publish now**, or queued pull, publishing, and Meta-validation work. Re-enable it only
  after reviewing its direction, capabilities, and credentials.
- **Pagination** — large catalogs are walked page by page automatically (Shopify follows the `Link`
  header, WooCommerce advances by `page`); Generic JSON sources can configure the pagination style. If
  a run reaches the 200-page safety limit while another page still exists, it finishes as
  **partial/truncated** and preserves the cursor; the next run resumes from that point. The cursor is
  cleared only after the feed actually reaches its end.
- **Format and products root** — Generic sources detect JSON, NDJSON, XML, CSV, or TSV from the response;
  you can choose a format manually. XML uses an **XPath** root (for example, `//products/product`); the
  other formats use a dot path.
- **Suggested mapping** — the preview suggests, but never saves by itself, Portuguese, English, and
  Spanish field matches with confidence. Review before applying. In addition to name and ID, price,
  compare-at price, currency, SKU, stock, brand, and external URL are mappable; `items.0.price` selects
  the first array position.
- **Source webhook** — each source has its own webhook address
  (`/webhooks/catalog/:account_id/:source_id`). Where
  the platform allows it, Conversa Labs registers it with one click via **Register webhook** (Nuvemshop,
  Kiwify); on others, you paste the address into the platform's own dashboard (Hotmart).
- **Inbound sync secret** — used by bulk-sync API clients and masked in the source list. **Rotate inbound
  secret** invalidates the previous value immediately, records the operation when the native audit
  trail is enabled, and reveals the new value once; update every sender.
- **Platform webhook secret** — a value provided by the platform to verify commerce events. It is
  write-only and never returned. To replace it, paste the new value while editing the source and update
  the external dashboard too; Conversa Labs does not invent or rotate that value on the platform.
- **Bidirectional Generic source** — configure the event map and field paths in the screen itself.
  Inbound requests require `X-Webhook-Signature: t=…,v1=…`, reject a source without a secret, enforce a
  replay window, and deduplicate the delivery ID. An outbound-only source refuses inbound deliveries.
  For outbound, provide an HTTP(S) destination without credentials, query parameters, or fragments;
  authentication uses the shared HMAC secret. Events have searchable history, automatic retries, and
  confirmed single or bulk manual replay. A delivery that
  finds the source disabled, deleted, changed, or without its secret fails before any external request
  and records the reason in that history.
- **Generic webhook product, variation, and items** — product and variation paths start at the event
  root. Set the items array path first, then map fields relative to each item. Blank fields are never
  inferred. Once mapped, values are snapshotted on the CRM order and sent only to account webhooks that
  opted in to **commerce details**.
- **Duplicate and loop protection** — every imported item keeps the origin identifier (`external_id` /
  `retailer_id`) and the source. On later syncs this updates the same product instead of recreating it,
  and prevents echoing a change back to the source it came from.

## Import historical Hotmart or Kiwify sales

For a saved Hotmart or Kiwify source, open **Management → Backfill sales**. Choose both dates within
the provider window: up to 31 calendar days for Hotmart or 90 days for Kiwify. You can filter by product
and by the provider's documented status/payment values; Kiwify also supports an affiliate filter. With
no Hotmart status filter, its API returns only `APPROVED` and `COMPLETE`; choose another documented status
explicitly when you need it. Click **Preview sales**: this call
is read-only, uses each provider's official pagination, and does not write a contact, organization,
event, or order. Review the local action for each row, then explicitly select at least one and at most
500 IDs before queuing the import. Omitting the selection never means “import everything.”

The import matches only existing account contacts through exact fields from that sales-list endpoint.
Hotmart Sales History provides buyer email (name/ucode are not identity matches); Kiwify `GET /sales`
provides email, mobile and CPF. An organization is associated only through the exactly matched contact's
current primary organization. It never guesses between conflicting matches or invents a CNPJ field that
the Kiwify list does not document. A buyer without an existing contact, or a provider state without a
faithful local meaning, is shown as non-importable; history
import never creates people or companies. Imported lifecycle events and CRM Orders preserve the
provider's order/approval timestamps and are marked historical. This suppresses customer messages,
automation fan-out, commission and ranking credit, engagement, CAPI, stock effects, and outbound account
webhooks while still populating the native order registry.

Use **Run history** to inspect selected, created, updated, repaired, skipped and failed counts, the exact
failed/skipped transaction IDs, and whether the global provider scan was truncated. An exact duplicate
request reuses the active run, and execution is locked per account/source. A completed or partial run
offers **Undo import** only while every locally created order/event is still untouched and unlinked; undo
is atomic, never contacts Hotmart/Kiwify, and never deletes contacts or organizations.

## Use cases

- Import a **Shopify** or **WooCommerce** store into the native catalog and serve customers from there.
- Publish native products to a **marketplace** (when the connector supports outbound).
- Keep **Mercado Livre** or **Nuvemshop** connected to feed the native catalog.
- Import **digital products** from **Hotmart** or **Kiwify** and still receive sale events in the
  conversation.

## Capabilities by platform

Each connector declares what it supports; the interface enables the direction and the buttons according
to that capability.

| Platform | Import (inbound) | Event webhook | Historical sales | Authentication |
|---|---|---|---|---|
| Generic source (JSON, NDJSON, XML, CSV, or TSV) | Yes | Yes (configurable HMAC signature) | No | Bearer, header, Basic, or URL query parameter |
| Shopify | Yes | — | No | Token / header |
| WooCommerce | Yes | — | No | Token / header |
| Magento, PrestaShop, Medusa | Yes | — | No | Token / header |
| Mercado Livre | Yes | — | No | OAuth (Authorize) |
| Nuvemshop | Yes | Yes (self-register) | No | Store token (paste) |
| Hotmart | Yes (products) | Yes (in Hotmart panel) | Yes (governed preview and selection) | Client credentials |
| Kiwify | Yes (products) | Yes (self-register) | Yes (governed preview and selection, up to 90 days) | Client credentials |
| OLX | No (no read API) | — | No | Partner only |

- **Publishing (outbound)** to the **WhatsApp Business Catalog** has its own article; the store/marketplace
  connectors above focus on **import** in this version. **Not every platform is bidirectional.**
- The **event webhooks** above deliver **sale events** (not products) and feed the **e-commerce
  lifecycle** — see that article.
- **OLX** offers no public read API: the integration exists only for approved partners, who publish an
  ad feed (autoupload). For that reason the OLX connector ships disabled in Sync Studio until partner
  access is granted.

## Tips, limits & best practices

- **Credentials stay on the server**: they are encrypted, never returned to the screen, and never appear
  in logs. OAuth connectors (Mercado Livre) **refresh the token on their own** through the granted
  authorization.
- **Respect the source platform's pagination and limits**; very large catalogs are read across several
  pages and may take longer on the first import.
- **The description arrives as plain text**: stores such as Nuvemshop/Tiendanube and Shopify keep
  the product description in HTML. On import the platform **converts it to text**, preserving
  paragraphs, line breaks and lists — the tags never reach you or the customer, since the
  description travels as text in the message sent in the conversation and in the Meta catalog. A
  description you type yourself is stored exactly as you wrote it.
- **Major units for money**: prices stay in major units (`4.97` = R$4.97). The platform does **not**
  divide by 100.
- Run the **first import outside peak hours** to review the result calmly.

## Troubleshooting

- **Mercado Livre authorization failed**: confirm the platform app uses the fixed return address
  `/catalog_oauth/callback` and redo the **Authorize** flow (the authorization `state` expires within a
  few minutes).
- **Products were not imported**: use **Test connection** to see the real response; check the token/keys,
  the `store_id`/`account_id` where applicable, and whether the chosen connector is the right one. The
  Generic preview shows the platform's reason with secrets removed.
- **The webhook does not fire**: confirm the source was **registered** (Nuvemshop/Kiwify) or that the
  address was pasted into the platform panel (Hotmart), and that the **webhook secret** is filled in.
- **Duplicate items**: duplication is avoided by the origin identifier (`retailer_id` / `external_id`);
  if duplicates appear, check whether the items arrived with identifiers different from what already
  existed.

## See also

- [Native catalog: products, categories, images, and prices](/hc/ajuda/articles/catalog-commerce-catalogo-nativo-en)
- [Sync and WhatsApp Business Catalog](/hc/ajuda/articles/catalog-commerce-sync-whatsapp-business-catalog-en)
- [E-commerce lifecycle: Kiwify/Hotmart/Nuvemshop/Shopify webhooks](/hc/ajuda/articles/catalog-commerce-commerce-lifecycle-en)