> ## Documentation Index
> Fetch the complete documentation index at: https://developers.gojoe.de/llms.txt
> Use this file to discover all available pages before exploring further.

# Stock and prices

> Push stock and prices from your ERP to the GO JOE shop.

Your ERP keeps the GO JOE shop's stock and prices up to date by pushing them.
GO JOE never pulls; what you push is what the shop sells.

## Your article numbers

You always talk about articles by **your own article number** (`pharmacy_sku`,
1 to 64 printable characters). GO JOE links each of your SKUs to a GO JOE
product once. Until that is done the SKU is `unmapped`: GO JOE stores what you
sent and shows it to its team for mapping, but the shop does not sell it yet.
You don't need to do anything for unmapped SKUs; keep pushing them.
The first time a push contains new unknown SKUs you also get one
`inventory.sku_unmapped` event (webhook and `GET /events`) listing them.

## Push stock and prices

```bash theme={null}
curl -X PUT "https://<base-url>/pharmacies/<pharmacy_id>/inventory?mode=partial" \
  -H "Authorization: Bearer gj_test_…" -H "Content-Type: application/json" \
  -H "Idempotency-Key: stock-2026-11-10T09:00" \
  -d '{"items": [
    {"pharmacy_sku": "4711", "name": "Pink Kush 22/1", "manufacturer": "Aurora", "form": "flower",
     "thc_percent": 22, "cbd_percent": 1, "available": true, "stock_grams": 340,
     "price_cents": 990, "min_order_grams": 5, "order_increment": 5}
  ]}'
```

* `name` and `available` are required; everything else is optional.
* `stock_grams` is grams (flower) or millilitres (extracts).
* `price_cents` is the **gross price per gram or millilitre** in cents, the
  unit the shop shows. GO JOE applies prices unless it has switched price sync
  off for the pharmacy; the response says so in `prices_applied`.
* Up to 1,000 items per push. Validation is all or nothing: if one item is
  invalid you get `422` with an `errors` list (index, SKU, field) and nothing
  is applied.

### `partial` or `full`

* `mode=partial` (default) changes only the items you send. Use it for
  updates during the day.
* `mode=full` says "this is my complete catalogue": mapped SKUs **missing**
  from the push are marked sold out. Use it for a nightly full sync. Send
  your whole catalogue in one push (up to 1,000 items).

### The response

```json theme={null}
{ "mode": "partial", "prices_applied": true,
  "summary": { "received": 1, "updated": 1, "unmapped": 0, "kept_off": 0, "warnings": 0, "missing_switched_off": 0 },
  "results": [ { "pharmacy_sku": "4711", "status": "updated", "product_id": "…", "warnings": [] } ] }
```

Per item, `status` is:

* `updated`: the shop now sells with your numbers.
* `unmapped`: stored, waiting for GO JOE to map it.
* `kept_off`: GO JOE's team switched this article off in the shop. Stock and
  prices still follow your push, but it stays off until GO JOE switches it
  back on.

## One article in real time

After a sale or a delivery, update one SKU. Fields you leave out keep the
value you pushed last:

```bash theme={null}
curl -X PATCH "https://<base-url>/pharmacies/<pharmacy_id>/inventory/4711" \
  -H "Authorization: Bearer gj_test_…" -H "Content-Type: application/json" \
  -d '{"stock_grams": 325}'
```

For a SKU you never pushed before, send at least `name` and `available`.

## Large price changes

A price change of more than 50 % up or down is applied, because you know your
prices, but GO JOE double-checks it: the item gets a `price_change_large`
warning with the old and new price, and GO JOE's team is notified. Nothing
for you to do unless the price was a typo; then push the correct one.

## Check what GO JOE holds

```bash theme={null}
curl "https://<base-url>/inventory?pharmacy_id=<pharmacy_id>" -H "Authorization: Bearer gj_test_…"
```

For every SKU you pushed you get what you sent (`pushed`), whether it is
mapped, and what the shop sells right now (`in_shop`).
The list is sorted by SKU and paged (200 per page, `limit` up to 500):
follow `next_cursor` until `has_more` is `false`.

## Keep it fresh

Push at least every few hours while the pharmacy is open, even if nothing
changed (a `partial` push with your current numbers is fine). If GO JOE hears
nothing from your ERP for 6 hours during opening hours it assumes the sync is
stuck and contacts you, because the shop would otherwise keep selling
yesterday's stock.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.