No description
  • JavaScript 100%
Find a file
Isac b545cfd7cf Document running the sync as a systemd service
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JMFHmkdVV3QgDgC196PAGQ
2026-09-13 18:41:59 +02:00
.env.example Sync SumUp card-reader sales to Shopify inventory 2026-09-13 18:31:57 +02:00
.gitignore Sync SumUp card-reader sales to Shopify inventory 2026-09-13 18:31:57 +02:00
lib.js Sync SumUp card-reader sales to Shopify inventory 2026-09-13 18:31:57 +02:00
package.json Sync SumUp card-reader sales to Shopify inventory 2026-09-13 18:31:57 +02:00
README.md Document running the sync as a systemd service 2026-09-13 18:41:59 +02:00
sync.js Sync SumUp card-reader sales to Shopify inventory 2026-09-13 18:31:57 +02:00
test.sync.js Sync SumUp card-reader sales to Shopify inventory 2026-09-13 18:31:57 +02:00

ecom-inventory-sync

Checks SumUp for new card-reader sales and lowers the stock count for the same items in Shopify.

It checks SumUp every 60 seconds (the interval is configurable). SumUp doesn't send real-time notifications for in-person sales made with the app, so polling is the only option.

How items are matched

SumUp sales records list each item by name only. There is no SKU field. So:

Name each product in your SumUp app catalog exactly the same as its Shopify variant SKU.

Case and extra spaces don't matter. If a sold item has no matching SKU, a warning is logged and Shopify isn't changed for that item.

Setup

  1. Shopify: Settings → Apps → Develop apps → create a custom app. Grant Admin API scopes read_products, read_inventory, write_inventory, read_locations. Install it and copy the Admin API access token.
  2. Shopify location ID: go to Settings → Locations and open the location. The number in the URL goes into gid://shopify/Location/<number>.
  3. SumUp: create an API key in the SumUp dashboard and note your merchant code.
  4. cp .env.example .env and fill it in.
  5. npm start (requires Node 20.6+; there are no dependencies to install).

Run npm test to check the matching logic.

Running on a server

Use a systemd service on a Linux server. The script runs as a never-ending loop, so systemd only needs to start it at boot and restart it if it crashes.

  1. Get the code onto the server (requires Node 20.6 or newer):

    git clone git@sshgit.yeold.org:yeold/ecom-inventory-sync.git ~/ecom-inventory-sync
    cd ~/ecom-inventory-sync
    cp .env.example .env && chmod 600 .env   # fill in your keys
    

    Cloning through sshgit.yeold.org requires cloudflared and the same SSH config on the server. Otherwise, copy the folder over with rsync or scp.

  2. Create /etc/systemd/system/ecom-inventory-sync.service:

    [Unit]
    Description=SumUp to Shopify inventory sync
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    User=youruser
    WorkingDirectory=/home/youruser/ecom-inventory-sync
    ExecStart=/usr/bin/node --env-file=.env sync.js
    Restart=always
    RestartSec=10
    
    [Install]
    WantedBy=multi-user.target
    
    • Replace youruser with the account that owns the folder.
    • Check the Node path with which node; with nvm it's a different, longer path.
    • WorkingDirectory matters because .env and state.json are found relative to it.
  3. Start it and enable it at boot:

    sudo systemctl daemon-reload
    sudo systemctl enable --now ecom-inventory-sync
    journalctl -u ecom-inventory-sync -f   # watch the logs
    

To update later, run git pull && sudo systemctl restart ecom-inventory-sync.

Notes

  • On the first run it starts from the current time. Past sales are not replayed.
  • Processed transaction IDs are saved in state.json, so a restart won't count the same sale twice.
  • Refunds are not handled. If you refund a sale, add the stock back in Shopify manually.