Guides

Send reorder points to a spreadsheet or another system

Copy each category's reorder points into Google Sheets, Excel or your own ERP on a schedule, with a fresh key for every run.

The pattern

Reorder points (the level that triggers a new order) are worked out when they are read, and Panlytics keeps no history of them. To use them somewhere else, or to keep a record over time, a program reads them and writes them where you want them.

Because keys end within hours, the program is built to run, finish, and let its key end:

  1. A person makes a key for the run, or a scheduled job asks the person for one.
  2. The program reads the categories it needs.
  3. It writes the figures to the spreadsheet or system.
  4. The key ends on its own.

Into a spreadsheet

The CSV export opens directly in Excel, Numbers and Google Sheets:

curl
curl "https://panlytics.net/api/v1/categories/40/reorder-points?format=csv" \
  -H "Authorization: Bearer $PANLYTICS_KEY" \
  -o "reorder-points-$(date +%F).csv"

Keeping one file per day gives you the history Panlytics does not store. In Google Sheets, File, then Import, then Upload brings a file in as a new sheet.

Into another system

A program that feeds an ERP reads the JSON and sends each row on. This one reads every category of one shop and posts the products to order to an address of your own:

Python
import os
import requests

API = "https://panlytics.net/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['PANLYTICS_KEY']}"}
ERP = os.environ["ERP_ORDERS_URL"]  # your own system


def every_row(path: str) -> list[dict]:
    """Every page of one list, read 200 rows at a time."""
    rows, cursor = [], None
    while True:
        params = {"limit": 200, **({"cursor": cursor} if cursor else {})}
        answer = requests.get(f"{API}{path}", headers=HEADERS, params=params, timeout=30)
        answer.raise_for_status()
        page = answer.json()
        rows.extend(page["data"])
        cursor = page["nextCursor"]
        if not cursor:
            return rows


for category in every_row("/shops/12/categories"):
    lines = every_row(f"/categories/{category['id']}/order-list")
    if lines:
        requests.post(ERP, json={"category": category["name"], "lines": lines}, timeout=30).raise_for_status()

Each row of the order list carries ean, name, orderPcs, packSize, orderValueEur, stockPcs and reorderPoint, among others. GET /v1/categories/{id}/order-list lists every field.

Doing it well

  • Read, then write. Never send a key or a figure to a system the person did not choose.
  • Stay under the limit. 120 calls a minute is plenty for a few hundred categories, but wait on a 429 as Rate limits shows.
  • Keep the CSV, not the key. The file is yours to keep. The key is not, and it ends anyway.
  • Export is audited. Each CSV export is written to the audit log under the key's maker, so the company can see where its figures went.