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

# Authentication

> How to authenticate with the Shoppex Developer API

<Info>
  If you are using **Claude Code, Codex, or an internal automation script** for themes, use an **API key** with scopes `themes.read themes.write`. Use OAuth2 only if you are building an external app that other merchants install.
</Info>

## Authentication Modes

Shoppex supports two Bearer token modes for the Dev API:

* API keys for server-to-server integrations you manage directly
* OAuth2 access tokens for installable apps and third-party connectors

Your own warehouse worker would use an API key. A third-party ERP or CRM would use OAuth2, so the merchant clicks "Connect Shoppex" instead of pasting a raw key.

## Quick Decision

Use this shortcut:

* **I run the tool myself** -> API key
* **I am building an installable third-party app** -> OAuth2

Claude Code editing your own theme? API key. Codex running your internal deployment helper? API key. ERP integration for many merchants? OAuth2.

<Tabs>
  <Tab title="API Keys">
    Shoppex uses API keys for authentication. Each key belongs to exactly one shop and can be limited with scopes.

    ### Creating an API Key

    <Steps>
      <Step title="Open Dashboard">
        Go to [dashboard.shoppex.io](https://dashboard.shoppex.io) and log in.
      </Step>

      <Step title="Navigate to Settings">
        Go to **Settings** in the sidebar.
      </Step>

      <Step title="Generate Key">
        In the **Developer API** section, click **Generate New API Key**.
      </Step>

      <Step title="Choose Access">
        Pick the smallest scope set your integration needs.

        Common scope combinations:

        | Integration                | Scopes                                                                                                                  |
        | -------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
        | Fulfillment / ERP sync     | `orders.read`                                                                                                           |
        | Chargeback tooling         | `disputes.read`                                                                                                         |
        | Report automation          | `analytics.read`, `analytics.write`                                                                                     |
        | Theme development          | `themes.read`, `themes.write`                                                                                           |
        | Catalog sync               | `products.read`                                                                                                         |
        | CRM sync                   | `customers.read`                                                                                                        |
        | Reseller program admin     | `reseller_programs.read`, `resellers.read`, `resellers.write`                                                           |
        | Reseller portal automation | `reseller_sales.read`, `reseller_payouts.read`, `reseller_payouts.write`, `reseller_stock.read`, `reseller_stock.write` |
        | Webhook management         | `webhooks.read`, `webhooks.write`                                                                                       |
      </Step>

      <Step title="Copy Key">
        Copy your API key immediately. It starts with `shx_` and won't be shown again.

        <Warning>
          Store your API key securely. If compromised, regenerate it immediately.
        </Warning>
      </Step>
    </Steps>

    ### Using Your API Key

    Include the API key in the `Authorization` header with the `Bearer` scheme:

    <CodeGroup>
      ```bash cURL theme={"system"}
      curl -X GET https://api.shoppex.io/dev/v1/invoices \
        -H "Authorization: Bearer shx_your_api_key_here"
      ```

      ```typescript TypeScript theme={"system"}
      const response = await fetch('https://api.shoppex.io/dev/v1/invoices', {
        headers: {
          'Authorization': 'Bearer shx_your_api_key_here'
        }
      });
      ```

      ```python Python theme={"system"}
      import requests

      response = requests.get(
          'https://api.shoppex.io/dev/v1/invoices',
          headers={'Authorization': 'Bearer shx_your_api_key_here'}
      )
      ```

      ```php PHP theme={"system"}
      $ch = curl_init('https://api.shoppex.io/dev/v1/invoices');
      curl_setopt($ch, CURLOPT_HTTPHEADER, [
          'Authorization: Bearer shx_your_api_key_here'
      ]);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      $response = curl_exec($ch);
      ```
    </CodeGroup>
  </Tab>

  <Tab title="OAuth2">
    OAuth2 is the better fit when you want an external app to connect to a shop without asking the merchant for a raw API key.

    ### Creating an OAuth App

    1. Log in to [dashboard.shoppex.io](https://dashboard.shoppex.io)
    2. Go to your Dev API settings
    3. Create an OAuth app with:
       * a name
       * one or more redirect URIs
       * the scopes the app may request
    4. Copy the `client_id` and `client_secret`

    For example: App name `ERP Connector`, redirect URI `https://erp.example.com/oauth/callback`, scopes `orders.read customers.read`.

    ### Authorize Endpoint

    The merchant browser is redirected to:

    ```bash theme={"system"}
    GET /dev/v1/oauth/authorize?response_type=code&client_id=shoc_xxx&redirect_uri=https%3A%2F%2Ferp.example.com%2Foauth%2Fcallback&scope=orders.read%20customers.read&state=sync_42
    ```

    If the user is logged in and allowed to approve integrations for the active shop, Shoppex first shows a Shoppex-hosted approval screen.

    After the merchant clicks **Approve and continue**, Shoppex issues a short-lived code and redirects back to your app.

    ```bash theme={"system"}
    https://erp.example.com/oauth/callback?code=shoa_abc123&state=sync_42
    ```

    Important:

    * the approval step is intentionally interactive, so a third-party site cannot silently mint OAuth codes for a logged-in merchant
    * the approval submit is protected with a Shoppex CSRF token behind the hosted approval page

    ### Token Endpoint

    Exchange that code for an access token:

    ```bash theme={"system"}
    curl https://api.shoppex.io/dev/v1/oauth/token \
      -X POST \
      -H "Authorization: Basic $(printf 'shoc_xxx:shcs_xxx' | base64)" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=authorization_code&code=shoa_abc123&redirect_uri=https%3A%2F%2Ferp.example.com%2Foauth%2Fcallback"
    ```

    Example response:

    ```json theme={"system"}
    {
      "access_token": "shpat_xxx",
      "token_type": "Bearer",
      "expires_in": 3600,
      "refresh_token": "shprt_xxx",
      "scope": "orders.read customers.read"
    }
    ```

    Refresh flow:

    ```bash theme={"system"}
    curl https://api.shoppex.io/dev/v1/oauth/token \
      -X POST \
      -H "Content-Type: application/json" \
      -d '{
        "grant_type": "refresh_token",
        "refresh_token": "shprt_xxx",
        "client_id": "shoc_xxx",
        "client_secret": "shcs_xxx"
      }'
    ```

    ### Using The Access Token

    After the exchange, call normal Dev API endpoints with the OAuth access token:

    ```bash theme={"system"}
    curl https://api.shoppex.io/dev/v1/orders \
      -H "Authorization: Bearer shpat_your_access_token_here"
    ```

    Important:

    * OAuth token responses follow the normal OAuth2 JSON format
    * normal `/dev/v1/*` resource calls still use the standard Shoppex Dev API response envelope
    * scopes still apply exactly the same way as for API keys
  </Tab>
</Tabs>

## Scopes

Scopes follow a `resource.action` format: `products.read`, `orders.write`, `themes.read`, etc. Use `*` for full access.

The most common mistake here is giving a key more scopes than it needs. A catalog sync should not also get `customers.write`. A reporting tool only needs read scopes. Grant the minimum and expand later if needed.

You can inspect the currently active key with:

```bash theme={"system"}
curl https://api.shoppex.io/dev/v1/me/capabilities \
  -H "Authorization: Bearer shx_your_api_key_here"
```

## Key Format

| Prefix   | Description                                  |
| -------- | -------------------------------------------- |
| `shx_`   | Shoppex API Key (32 characters after prefix) |
| `shoc_`  | OAuth client id                              |
| `shcs_`  | OAuth client secret                          |
| `shoa_`  | OAuth authorization code                     |
| `shpat_` | OAuth access token                           |
| `shprt_` | OAuth refresh token                          |

Example: `shx_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6`

## Error Responses

### Missing or Invalid Key

```json theme={"system"}
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Missing or invalid API key. Expected: Authorization: Bearer shx_...",
    "doc_url": "https://docs.shoppex.io/api-reference/errors"
  }
}
```

### Shop Suspended

```json theme={"system"}
{
  "error": {
    "code": "FORBIDDEN",
    "message": "Your shop has been suspended.",
    "doc_url": "https://docs.shoppex.io/api-reference/errors"
  }
}
```

### Missing Scope

```json theme={"system"}
{
  "error": {
    "code": "FORBIDDEN",
    "message": "Missing required API scope.",
    "doc_url": "https://docs.shoppex.io/api-reference/errors"
  }
}
```

## Regenerating Keys

If an API key is compromised:

1. Go to **Settings** in your dashboard
2. Revoke the affected key
3. Create a new key with the smallest required scopes
4. Update your integration with the new key

The old key is immediately invalidated. All requests using it will fail with `401 Unauthorized`.

## Best Practices

<AccordionGroup>
  <Accordion title="Use least privilege scopes">
    Give every integration only the scopes it really needs. A reporting tool needs `products.read` and `payments.read` — not `*`.
  </Accordion>

  <Accordion title="Handle rate-limit headers">
    Read `X-RateLimit-Remaining` and `Retry-After`. When remaining hits `0`, back off until the reset window passes instead of hammering the API.
  </Accordion>

  <Accordion title="Forward a request id">
    If your worker is processing `job_123`, send `X-Request-Id: job_123` so your logs and Shoppex support traces line up perfectly.
  </Accordion>

  <Accordion title="Use environment variables">
    Never hardcode API keys in your source code.

    ```bash theme={"system"}
    export SHOPPEX_API_KEY=shx_your_api_key_here
    ```

    ```typescript theme={"system"}
    const apiKey = process.env.SHOPPEX_API_KEY;
    ```
  </Accordion>

  <Accordion title="Keep keys server-side">
    Never expose your API key in client-side code (browsers, mobile apps).
    Make API calls from your backend server.
  </Accordion>

  <Accordion title="Use HTTPS only">
    Always use HTTPS when making API requests to prevent key interception.
  </Accordion>

  <Accordion title="Monitor usage">
    Check your dashboard regularly for unusual API activity.
  </Accordion>
</AccordionGroup>
