Guides

Upload a report

Send a shop's sales export to Panlytics through the API, to start a new category or bring the next period into one that exists.

What you need

  • A key whose maker's role holds Edit the sheet and upload a report. A new category needs it over the whole shop; the next report of a category needs it in that category.
  • The shop's id. GET /v1/shops lists the shops the key reaches, with their ids.
  • The report: the sales export your till or ERP already makes, as .xlsx or .csv. The limit is the same as in the app: at most 8 MB.

The full request and answer are on the reference page, POST /v1/shops/{id}/reports.

Start a new category

Send the file as multipart/form-data, with a category field naming the new category and periodDays, the number of days the report covers:

curl -X POST https://panlytics.net/api/v1/shops/12/reports \
  -H "Authorization: Bearer $PANLYTICS_KEY" \
  -H "Idempotency-Key: soft-drinks-2026-10-25" \
  -F "category=Soft drinks" \
  -F "periodDays=30" \
  -F "file=@soft-drinks.xlsx"

The answer is 201 with the new report and its category:

201
{
  "reportId": 311,
  "categoryId": 40,
  "shopId": 12,
  "newCategory": true,
  "rows": 412,
  "deduplicated": false
}

Panlytics reads the rows, repairs what it can and flags what it cannot, exactly as it does for a report uploaded in the app. deduplicated is true when this exact file was uploaded before. If the shop already has a category with that name, the report becomes that category's next report, and newCategory is false.

Bring the next period into a category

To file the next report into a category that exists, send categoryId instead of category. periodDays is optional here: left out, the category keeps its period. GET /v1/shops/{id}/categories lists the categories with their ids.

curl
curl -X POST https://panlytics.net/api/v1/shops/12/reports \
  -H "Authorization: Bearer $PANLYTICS_KEY" \
  -H "Idempotency-Key: soft-drinks-2026-11-01" \
  -F "categoryId=40" \
  -F "file=@soft-drinks-november.xlsx"

Send it once

When it is refused

CodeStatusWhat to change
api.invalid400detail names the field: no file, both or neither of category and categoryId, or no periodDays for a new category.
upload.said400The file failed a check, such as its type. detail says what. Send .xlsx or .csv.
upload.too_large413Send a file under 8 MB.
form.field422What the file holds was refused. detail says why.
refused403The key's maker may not upload to this shop or category.
refused.demo403A shared demo account cannot upload.
not_found.said404The shop or category id is wrong, or the category is not in this shop.

An agent should ask its person before it uploads anything, as the agent prompt tells it to. Every upload is written to the audit log under the maker's name.