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

# Authentication

> JWT-based authentication, email verification, roles, and 2FA

The API uses **RS256-signed JWT bearer tokens**. There is no API-key mode — every authenticated
request carries a per-user access token obtained through the auth flow below.

## Roles

Every account has one or more roles, carried as claims inside the access token:

| Role          | Meaning                                                                                   |
| ------------- | ----------------------------------------------------------------------------------------- |
| `RETAIL`      | A regular storefront customer (asikoexpress.com)                                          |
| `TRADE`       | A wholesale/B2B account (asikofoods.com), created via the wholesale application flow      |
| `SALES_REP`   | Internal sales staff                                                                      |
| `ADMIN`       | Back-office staff — user management, wholesale application review, order tracking updates |
| `SUPER_ADMIN` | Everything `ADMIN` can do, plus role assignment and account suspension                    |

Endpoints under **API Reference → Admin**, and the write endpoints under **Inventory (Admin)**,
require `ADMIN` or `SUPER_ADMIN`. Everything else that requires auth accepts any authenticated
user unless the endpoint description says otherwise.

## Retail sign-up

<Steps>
  <Step title="Register">
    `POST /v1/auth/register` with email, password, first/last name, and phone. The account is
    created unverified and a 6-digit code is emailed to the address given.
  </Step>

  <Step title="Verify email">
    `POST /v1/auth/verify-email` with the email and code. The code expires 10 minutes after
    it's sent — use `POST /v1/auth/verify-email/resend` to get a new one. On success, this
    returns the same token pair as login.
  </Step>

  <Step title="Log in">
    `POST /v1/auth/login` with email and password returns `accessToken`, `refreshToken`, and
    `expiresIn` (seconds).
  </Step>
</Steps>

## Wholesale (trade) sign-up

Trade accounts go through a review step rather than self-serve verification:

1. `POST /v1/wholesale/apply` — public, no password collected. Returns a human-readable tracking
   ID (e.g. `CRA-2658190`). This creates the account under review; no login is possible yet.
2. An admin approves or rejects the application (`API Reference → Admin → Wholesale
   Applications`).
3. On approval, a set-password code is emailed. `POST /v1/wholesale/set-password` with that code
   activates the account and returns a token pair.

## Using the access token

Send it as a standard bearer token on every authenticated request:

```
Authorization: Bearer <accessToken>
```

Access tokens are short-lived (15 minutes). When one expires, call `POST /v1/auth/refresh` with
the refresh token (valid 7 days) to get a new pair. `POST /v1/auth/logout` invalidates the
current refresh token.

<Warning>
  There's no token-refresh middleware baked into this API — client applications are expected to
  catch `401`s and call `/v1/auth/refresh` themselves before retrying.
</Warning>

## Two-factor authentication (TOTP)

Any authenticated user can turn on TOTP (Google Authenticator-style) 2FA:

* `POST /v1/auth/totp/setup` — generates a secret and QR code.
* `POST /v1/auth/totp/verify` — confirms the code from the authenticator app and turns 2FA on.
* `POST /v1/auth/totp/disable` — turns it back off.

## Optional auth

A few catalogue endpoints (product detail, "just for you" recommendations) accept a bearer token
if present but don't require one — pass a token to personalize the response, or omit it entirely
for anonymous browsing. These are called out individually in the reference.
