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

# Shops and access

> Team roles, granular permissions, and cross-shop isolation.

A user can own several shops and belong to other shops' teams. Every request containing `{shopId}` is checked against that exact shop; a resource identifier such as a product or server must belong to it as well.

## Role presets

| Role      | Default scope                                                                            |
| --------- | ---------------------------------------------------------------------------------------- |
| `viewer`  | read shop, products, orders, and statistics                                              |
| `support` | handle orders; read products, statistics, and team                                       |
| `manager` | manage products, orders, discounts, and vouchers; read servers, payments, and statistics |
| `admin`   | operational management across the shop                                                   |
| owner     | full control, including shop deletion and owner-only decisions                           |

Legacy `view`, `edit`, and `full` roles map to `viewer`, `manager`, and `admin`. Individual `customPermissions` can extend a role.

<Warning>
  A team member cannot receive the `owner` role or the global `*` wildcard. Someone with `team:manage` may delegate only a subset of their own effective permissions.
</Warning>

## Add an existing user

The endpoint requires `team:manage` and accepts a Bearer session or a suitably scoped `shop` key.

```bash theme={null}
curl -X POST https://api.itemshop.dev/api/v2/shops/<shopId>/team \
  -H "X-API-Key: <shop-key>" \
  -H "Content-Type: application/json" \
  -d '{ "userId": "<userId>", "roles": ["support"], "customPermissions": [] }'
```

Remove a member:

```bash theme={null}
curl -X DELETE https://api.itemshop.dev/api/v2/shops/<shopId>/team/<userId> \
  -H "X-API-Key: <shop-key>"
```

The dashboard also supports invite links with an expiry, use limit, and predefined scope. Joining creates a request that someone with sufficient scope approves or denies.

## Access-control responses

* invalid `shopId` format → `400`;
* missing or invalid authentication → `401`;
* valid identity but insufficient scope or a different shop → `403`;
* missing shop or resource inside that shop → `404`.

Access results are cached briefly. Team and key changes invalidate the relevant cache entries so revoked access does not wait for natural expiry.
