Repository navigation
Syncing Data
This page explains how Clone Sheet connects to your shop, which data it copies, how incremental sync works and what happens when you switch shops or clear data. It also lists the local endpoints you can call to automate syncs.
The Create Access Token button opens:
https://selldone.com/auth/erp?scopes[]=selldone:identification&scopes[]=backoffice:shop:read&scopes[]=backoffice:order:read&scopes[]=backoffice:product:read&scopes[]=backoffice:category:read&scopes[]=backoffice:customer:read
The requested scopes are selldone:identification, backoffice:shop:read, backoffice:order:read,
backoffice:product:read, backoffice:category:read and backoffice:customer:read. No write scope is requested, and
Clone Sheet only sends GET requests to the Selldone API. The token page is the same one used by ERP
integrations; see Token Generation in the ERP wiki. View and
revoke tokens at selldone.com/developer/access.
When you click Save & Connect, Clone Sheet:
- Saves the token in the
key_valuestable asauth_token(adding theBearerprefix if it is missing). - Fetches your user profile from
https://api.selldone.com/userand saves it inusers. - Fetches the shop from
https://api.selldone.com/shops/{shop_id}/database/shop/sync, saves it inshopsand stores the shop ID asselected_shop_id.
| Resource | Local table | Remote endpoint |
|---|---|---|
| Categories | categories |
GET https://api.selldone.com/shops/{shop_id}/database/categories/sync |
| Products | products |
GET https://api.selldone.com/shops/{shop_id}/database/products/sync |
| Product Variants | product_variants |
GET https://api.selldone.com/shops/{shop_id}/database/product-variants/sync |
| Customers | customers |
GET https://api.selldone.com/shops/{shop_id}/database/customers/sync |
| Shop Data | shop_data |
GET https://api.selldone.com/shops/{shop_id}/database/shop-data/sync |
| Baskets | baskets |
GET https://api.selldone.com/shops/{shop_id}/database/baskets/sync |
| Basket Items | basket_items |
GET https://api.selldone.com/shops/{shop_id}/database/basket-items/sync |
Sync All Resources in the Sync tab runs them one after another in this order.
For each resource, Clone Sheet:
- Reads the token, the shop ID and the resource's last sync time (
<resource>_last_updated_at) fromkey_values. - Requests the first batch with
updated_at=<last sync time>,limit=100andoffset=0. - Reads the records from the response key named after the resource (for example
products) and thetotalcount. - Upserts every record into the local table by primary key. A record that fails is logged and counted, and the sync continues.
- Requests the next batch (
offset+ 100) while a full batch of 100 was returned. - Saves the current time as the new
<resource>_last_updated_at.
The first sync has no last sync time, so it copies everything. Later syncs only fetch records updated since then. If
the response is empty, the status shows already up to date. Progress messages are streamed to the browser with
server-sent events from /progress/stream.
If you connect a different shop ID than the one already stored, Clone Sheet first clears the synced tables, resets the sync times and removes the stored shop. The database always holds the data of one shop.
Database tab → Clear All Data truncates the synced tables (categories, products, product_variants,
customers, shop_data, baskets, basket_items) and resets the sync times. The token, shop and user profile are
kept. The next sync downloads everything again. This cannot be undone.
The web UI calls local HTTP endpoints, so you can trigger the same actions from scripts or a scheduler while the app
is running (replace 3010 with your port):
curl -X POST http://localhost:3010/products/fetch-products
curl -X POST http://localhost:3010/baskets/fetch-baskets| Method | Path | Action |
|---|---|---|
POST |
/auth/set-token |
Save the token. Body: { "token": "<token>" }. |
POST |
/user/fetch-user |
Fetch and save your user profile. |
POST |
/shop/fetch-shop |
Fetch and save the shop. Body: { "shop_id": "<id>" }. |
GET |
/me |
Return the connected shop from the local database. |
POST |
/categories/fetch-categories |
Sync categories. |
POST |
/products/fetch-products |
Sync products. |
POST |
/product-variants/fetch-product-variants |
Sync product variants. |
POST |
/customers/fetch-customers |
Sync customers. |
POST |
/shop-data/fetch-shop-data |
Sync shop data. |
POST |
/baskets/fetch-baskets |
Sync baskets. |
POST |
/basket-items/fetch-basket-items |
Sync basket items. |
GET |
/database/get-table-data/:key |
Read a table (see Exploring and Visualizing). |
POST |
/admin/clear-database |
Clear all synced data. |
GET |
/progress/stream |
Server-sent events with sync progress. |
Each sync endpoint returns JSON such as
{ "success": true, "message": "... 120 products updated successfully!", "fetchedCount": 120 }. These endpoints have
no authentication; keep the app on a trusted machine.