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

# Custom Storefront Tokens

> Generate, manage, and validate API tokens for custom storefronts connecting to your store.

Custom Storefront Tokens allow store owners to generate API keys that external developers can use to build custom storefronts. Tokens are scoped by domain, environment, and permissions.

***

## POST /custom/tokens

Generate a new API token for a custom storefront domain.

### Authentication

Requires Bearer token (`auth:customer_api`).

### Headers

| Header        | Value            | Required |
| ------------- | ---------------- | -------- |
| Authorization | Bearer {token}   | Yes      |
| Content-Type  | application/json | Yes      |

### Body Parameters

| Parameter   | Type   | Required | Description                                                                                                         |
| ----------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------- |
| domain      | string | Yes      | The domain where the token will be used (max 255 chars). Production domains must use HTTPS and cannot be localhost. |
| permissions | array  | Yes      | Array of permission strings (minimum 1)                                                                             |
| environment | string | Yes      | Either `development` or `production`                                                                                |

### Available Permissions

| Permission        | Description                |
| ----------------- | -------------------------- |
| `read_products`   | Read product data          |
| `read_categories` | Read category data         |
| `read_orders`     | Read order data            |
| `read_store`      | Read store information     |
| `read_analytics`  | Read analytics data        |
| `write_cart`      | Manage cart operations     |
| `write_wishlist`  | Manage wishlist operations |

<Warning>
  Development tokens are limited to `read_products`, `read_categories`, and `read_store` permissions only. Requesting other permissions for a development token will return an error.
</Warning>

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://front.rmz.gg/api/custom/tokens" \
    -H "Authorization: Bearer 1|abc123xyz..." \
    -H "Content-Type: application/json" \
    -d '{
      "domain": "https://mystore.example.com",
      "permissions": ["read_products", "read_categories", "read_store", "write_cart"],
      "environment": "production"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://front.rmz.gg/api/custom/tokens", {
    method: "POST",
    headers: {
      "Authorization": "Bearer 1|abc123xyz...",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      domain: "https://mystore.example.com",
      permissions: ["read_products", "read_categories", "read_store", "write_cart"],
      environment: "production"
    })
  });
  const data = await response.json();
  ```

  ```python Python theme={null}
  response = requests.post("https://front.rmz.gg/api/custom/tokens",
      headers={"Authorization": "Bearer 1|abc123xyz..."},
      json={
          "domain": "https://mystore.example.com",
          "permissions": ["read_products", "read_categories", "read_store", "write_cart"],
          "environment": "production"
      }
  )
  data = response.json()
  ```

  ```php PHP theme={null}
  $response = Http::withToken("1|abc123xyz...")->post("https://front.rmz.gg/api/custom/tokens", [
      "domain" => "https://mystore.example.com",
      "permissions" => ["read_products", "read_categories", "read_store", "write_cart"],
      "environment" => "production"
  ]);
  $data = $response->json();
  ```
</CodeGroup>

### Response

#### Success (200)

```json theme={null}
{
  "success": true,
  "data": {
    "id": 1,
    "token": "cst_42_a1b2c3d4e5f6...",
    "domain": "https://mystore.example.com",
    "permissions": ["read_products", "read_categories", "read_store", "write_cart"],
    "environment": "production",
    "expires_at": "2025-06-15T00:00:00.000000Z",
    "created_at": "2024-06-15T10:30:00.000000Z",
    "usage_note": "Store this token securely. It will not be shown again."
  },
  "message": "API token generated successfully"
}
```

<Warning>
  The raw token value is only returned once at creation time. Store it securely -- it cannot be retrieved again. The token is stored as a SHA-256 hash on the server.
</Warning>

#### Error Responses

| Status | Description                                                                                                     |
| ------ | --------------------------------------------------------------------------------------------------------------- |
| 400    | Production domain uses localhost, production domain not HTTPS, or development token with restricted permissions |
| 401    | Not authenticated                                                                                               |
| 409    | Token already exists for this domain and environment                                                            |
| 422    | Validation error                                                                                                |

### Token Expiry

| Environment   | Expires After |
| ------------- | ------------- |
| `development` | 30 days       |
| `production`  | 1 year        |

***

## GET /custom/tokens

List all tokens for the authenticated customer's store.

### Authentication

Requires Bearer token (`auth:customer_api`).

### Headers

| Header        | Value          | Required |
| ------------- | -------------- | -------- |
| Authorization | Bearer {token} | Yes      |

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://front.rmz.gg/api/custom/tokens" \
    -H "Authorization: Bearer 1|abc123xyz..."
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://front.rmz.gg/api/custom/tokens", {
    headers: { "Authorization": "Bearer 1|abc123xyz..." }
  });
  const data = await response.json();
  ```

  ```python Python theme={null}
  response = requests.get("https://front.rmz.gg/api/custom/tokens", headers={
      "Authorization": "Bearer 1|abc123xyz..."
  })
  data = response.json()
  ```

  ```php PHP theme={null}
  $response = Http::withToken("1|abc123xyz...")->get("https://front.rmz.gg/api/custom/tokens");
  $data = $response->json();
  ```
</CodeGroup>

### Response

#### Success (200)

```json theme={null}
{
  "success": true,
  "data": [
    {
      "id": 1,
      "domain": "https://mystore.example.com",
      "permissions": ["read_products", "read_categories", "read_store", "write_cart"],
      "environment": "production",
      "is_active": true,
      "last_used_at": "2024-06-15T12:00:00.000000Z",
      "usage_count": 1500,
      "expires_at": "2025-06-15T00:00:00.000000Z",
      "created_at": "2024-06-15T10:30:00.000000Z"
    }
  ]
}
```

<Note>
  The raw token value is never returned in list responses. Only metadata is shown.
</Note>

***

## DELETE /custom/tokens/{tokenId}

Revoke (deactivate) a token.

### Authentication

Requires Bearer token (`auth:customer_api`).

### Path Parameters

| Parameter | Type    | Description        |
| --------- | ------- | ------------------ |
| tokenId   | integer | Token ID to revoke |

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE "https://front.rmz.gg/api/custom/tokens/1" \
    -H "Authorization: Bearer 1|abc123xyz..."
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://front.rmz.gg/api/custom/tokens/1", {
    method: "DELETE",
    headers: { "Authorization": "Bearer 1|abc123xyz..." }
  });
  const data = await response.json();
  ```

  ```python Python theme={null}
  response = requests.delete("https://front.rmz.gg/api/custom/tokens/1", headers={
      "Authorization": "Bearer 1|abc123xyz..."
  })
  data = response.json()
  ```

  ```php PHP theme={null}
  $response = Http::withToken("1|abc123xyz...")->delete("https://front.rmz.gg/api/custom/tokens/1");
  $data = $response->json();
  ```
</CodeGroup>

### Response

#### Success (200)

```json theme={null}
{
  "success": true,
  "data": null,
  "message": "Token revoked successfully"
}
```

#### Error Responses

| Status | Description       |
| ------ | ----------------- |
| 401    | Not authenticated |
| 404    | Token not found   |

***

## GET /custom/tokens/{tokenId}/stats

Get usage statistics for a specific token.

### Authentication

Requires Bearer token (`auth:customer_api`).

### Path Parameters

| Parameter | Type    | Description |
| --------- | ------- | ----------- |
| tokenId   | integer | Token ID    |

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://front.rmz.gg/api/custom/tokens/1/stats" \
    -H "Authorization: Bearer 1|abc123xyz..."
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://front.rmz.gg/api/custom/tokens/1/stats", {
    headers: { "Authorization": "Bearer 1|abc123xyz..." }
  });
  const data = await response.json();
  ```

  ```python Python theme={null}
  response = requests.get("https://front.rmz.gg/api/custom/tokens/1/stats", headers={
      "Authorization": "Bearer 1|abc123xyz..."
  })
  data = response.json()
  ```

  ```php PHP theme={null}
  $response = Http::withToken("1|abc123xyz...")->get("https://front.rmz.gg/api/custom/tokens/1/stats");
  $data = $response->json();
  ```
</CodeGroup>

### Response

#### Success (200)

```json theme={null}
{
  "success": true,
  "data": {
    "usage_count": 1500,
    "last_used_at": "2024-06-15T12:00:00.000000Z",
    "created_at": "2024-06-15T10:30:00.000000Z",
    "is_active": true,
    "environment": "production",
    "days_until_expiry": 365
  }
}
```

#### Error Responses

| Status | Description       |
| ------ | ----------------- |
| 401    | Not authenticated |
| 404    | Token not found   |

***

## POST /custom/tokens/validate

Validate a custom storefront token. This is a public endpoint that does not require Bearer authentication.

### Authentication

None required. The token to validate is passed in the request body.

### Headers

| Header       | Value            | Required |
| ------------ | ---------------- | -------- |
| Content-Type | application/json | Yes      |

### Body Parameters

| Parameter | Type   | Required | Description                     |
| --------- | ------ | -------- | ------------------------------- |
| token     | string | Yes      | The raw token value to validate |

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://front.rmz.gg/api/custom/tokens/validate" \
    -H "Content-Type: application/json" \
    -d '{"token": "cst_42_a1b2c3d4e5f6..."}'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://front.rmz.gg/api/custom/tokens/validate", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ token: "cst_42_a1b2c3d4e5f6..." })
  });
  const data = await response.json();
  ```

  ```python Python theme={null}
  response = requests.post("https://front.rmz.gg/api/custom/tokens/validate", json={
      "token": "cst_42_a1b2c3d4e5f6..."
  })
  data = response.json()
  ```

  ```php PHP theme={null}
  $response = Http::post("https://front.rmz.gg/api/custom/tokens/validate", [
      "token" => "cst_42_a1b2c3d4e5f6..."
  ]);
  $data = $response->json();
  ```
</CodeGroup>

### Response

#### Valid Token (200)

```json theme={null}
{
  "success": true,
  "data": {
    "valid": true,
    "store_id": 42,
    "permissions": ["read_products", "read_categories", "read_store", "write_cart"],
    "environment": "production"
  }
}
```

#### Error Responses

| Status | Description                                                                         |
| ------ | ----------------------------------------------------------------------------------- |
| 401    | Invalid or expired token                                                            |
| 403    | Token domain mismatch (production tokens are validated against the `Origin` header) |
| 422    | Validation error (missing token)                                                    |

<Note>
  For production tokens, the `Origin` or `Referer` header of the request must match the domain registered with the token. Development tokens skip this check.
</Note>

***

## GET /custom/tokens/permissions

Get the permissions and metadata for a token identified by the `X-Custom-Token` header. This is a public endpoint.

### Authentication

None required. Pass the token via the `X-Custom-Token` header.

### Headers

| Header         | Value   | Required |
| -------------- | ------- | -------- |
| X-Custom-Token | {token} | Yes      |

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://front.rmz.gg/api/custom/tokens/permissions" \
    -H "X-Custom-Token: cst_42_a1b2c3d4e5f6..."
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://front.rmz.gg/api/custom/tokens/permissions", {
    headers: { "X-Custom-Token": "cst_42_a1b2c3d4e5f6..." }
  });
  const data = await response.json();
  ```

  ```python Python theme={null}
  response = requests.get("https://front.rmz.gg/api/custom/tokens/permissions", headers={
      "X-Custom-Token": "cst_42_a1b2c3d4e5f6..."
  })
  data = response.json()
  ```

  ```php PHP theme={null}
  $response = Http::withHeaders(["X-Custom-Token" => "cst_42_a1b2c3d4e5f6..."])
      ->get("https://front.rmz.gg/api/custom/tokens/permissions");
  $data = $response->json();
  ```
</CodeGroup>

### Response

#### Success (200)

```json theme={null}
{
  "success": true,
  "data": {
    "permissions": ["read_products", "read_categories", "read_store", "write_cart"],
    "environment": "production",
    "domain": "https://mystore.example.com",
    "expires_at": "2025-06-15T00:00:00.000000Z"
  }
}
```

#### Error Responses

| Status | Description                        |
| ------ | ---------------------------------- |
| 401    | Missing, invalid, or expired token |
