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

# API conventions

> Authentication, seller scoping, pagination, field selection, and webhooks shared by every Mercur API surface.

Every Mercur API surface follows the same rules for authentication, pagination, and field selection.

Mercur exposes three HTTP surfaces on the Medusa server. They share the conventions below, so once you learn one surface the others behave the same way.

| Surface                                 | Base path   | Audience             | Authentication                           |
| --------------------------------------- | ----------- | -------------------- | ---------------------------------------- |
| [Admin API](/rc/references/api/admin)   | `/admin/*`  | Marketplace operator | Medusa admin user (session or bearer)    |
| [Vendor API](/rc/references/api/vendor) | `/vendor/*` | Sellers              | Member auth + seller scoping (below)     |
| [Store API](/rc/references/api/store)   | `/store/*`  | Storefront           | Mostly public; customer auth where noted |

All requests and responses are JSON. Call these APIs with the typed `@mercurjs/client`. Every route below maps 1:1 to a client call.

## Authentication

### Admin

Admin routes use standard Medusa admin authentication. Log in via `/auth/user/emailpass`, then send the session cookie or an `Authorization: Bearer <token>` header.

### Vendor

Vendor routes authenticate the **member** actor (`/auth/member/emailpass` to obtain a token) and are additionally scoped to a single seller:

1. The request must carry an `x-seller-id` header, or a seller selected in the session via `POST /vendor/sellers/select`.
2. Middleware verifies the authenticated member belongs to that seller and populates the request's seller context. Every query and mutation on the surface is then filtered to that seller automatically.
3. The member's RBAC roles are resolved for the selected seller.

A handful of vendor routes are public by design: seller registration (`POST /vendor/sellers`), invite acceptance (`POST /vendor/members/invites/accept`), `GET /vendor/stores`, and `GET /vendor/feature-flags`.

### Store

Store routes are public. Customer authentication (session or bearer) is **required** for `/store/order-groups` and **optional** for `/store/offers` and `/store/products`, where it enriches the pricing context when present. Public seller routes only return sellers whose status is `open` and who are not inside a scheduled closure window.

## Pagination

List endpoints use offset pagination with two query parameters:

```
GET /admin/sellers?limit=20&offset=40
```

| Parameter | Description                         | Default                                      |
| --------- | ----------------------------------- | -------------------------------------------- |
| `limit`   | Maximum number of records to return | 50 for most routes (some use 10, 20, or 200) |
| `offset`  | Number of records to skip           | 0                                            |

Every list response carries the paging envelope alongside the records:

```json theme={null}
{
  "sellers": [ ... ],
  "count": 133,
  "offset": 40,
  "limit": 20
}
```

`count` is the total number of records matching the filters, so `offset + limit < count` means more pages exist.

## Field selection

List and detail endpoints accept a `fields` query parameter to control which fields and relations are returned:

```
GET /vendor/products?fields=id,title,+variants.sku,-description
```

* `+field` adds a field or relation **on top of** the route's defaults.
* `-field` removes one from the defaults.
* A bare `field` (no prefix) **replaces** the default set entirely.

<Warning>
  Mixing one unprefixed field into an otherwise-prefixed list switches the
  whole parameter to replace mode and silently drops the route defaults.
  Prefix every entry with `+` or `-` when you mean to merge.
</Warning>

## Filtering and ordering

List endpoints accept entity-specific filter parameters (documented per route group), a free-text `q` search parameter where the entity has searchable fields, and `order` for sorting (`order=-created_at` for descending).

## Errors

Errors follow Medusa's format:

```json theme={null}
{
  "type": "invalid_data",
  "message": "Seller with handle already exists"
}
```

Common types: `invalid_data` (400), `unauthorized` (401), `not_allowed` (403), `not_found` (404). The typed client throws these as `ClientError`.

## Webhooks

| Method | Path            | Purpose                                                                                                                                             |
| ------ | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST` | `/hooks/payout` | Payout provider webhook receiver. The registered provider (e.g. Stripe Connect) verifies the signature and resolves the event into a payout action. |

## Next steps

<CardGroup cols={3}>
  <Card title="Admin API" href="/rc/references/api/admin" />

  <Card title="Vendor API" href="/rc/references/api/vendor" />

  <Card title="Store API" href="/rc/references/api/store" />
</CardGroup>
