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

# Browser Session

> Generates an access token for Cart API authentication

## Overview

Browser Session is the authentication endpoint that serves as the starting point for all Cart API integrations. It exchanges your Application ID for an access token that authenticates subsequent API calls.

## Authentication

<ParamField header="x-firmly-app-id" type="string" required>
  Your Application ID provided by Firmly
</ParamField>

## Request Body (Optional)

<ParamField body="access_token" type="string">
  An expired access token (valid up to 1 week after expiration) to renew
</ParamField>

## Response

<ResponseField name="device_created" type="boolean">
  Indicates whether or not a new device was created for this session
</ResponseField>

<ResponseField name="access_token" type="string">
  The JWT access token to use in x-firmly-authorization header for all API calls
</ResponseField>

<ResponseField name="expires_in" type="number">
  Number of seconds until the token expires (typically 3600)
</ResponseField>

<ResponseField name="expires" type="number">
  Unix timestamp when the token expires
</ResponseField>

<ResponseField name="device_id" type="string">
  Unique identifier for this device session
</ResponseField>

## Code Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.firmly.work/api/v1/browser-session \
    -H "x-firmly-app-id: YOUR_APPLICATION_ID"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.firmly.work/api/v1/browser-session', {
    method: 'POST',
    headers: {
      'x-firmly-app-id': 'YOUR_APPLICATION_ID'
    }
  });

  const { access_token, expires_in } = await response.json();
  console.log(`Token expires in ${expires_in} seconds`);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.firmly.work/api/v1/browser-session',
      headers={'x-firmly-app-id': 'YOUR_APPLICATION_ID'}
  )

  data = response.json()
  access_token = data['access_token']
  expires_in = data['expires_in']
  print(f"Token expires in {expires_in} seconds")
  ```
</CodeGroup>

<ResponseExample>
  ```json theme={null}
  {
    "device_created": true,
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXZpY2VfaWQiOiI4MmIxMDUyMi01NDgzLTQ3MTktYjU5OS02ZDc4YjEyODI3ZjAiLCJhcHBfaWQiOiJhcHAtMTIzNDU2IiwiZXhwIjoxNjg4OTk4NTcyLCJpYXQiOjE2ODg5OTQ5NzJ9.signature",
    "expires_in": 3600,
    "expires": 1688998572,
    "device_id": "82b10522-5483-4719-b599-6d78b12827f0"
  }
  ```
</ResponseExample>

## Token Renewal

You can renew an expired token up to 1 week after expiration:

<CodeGroup>
  ```bash Using Body Parameter theme={null}
  curl -X POST https://api.firmly.work/api/v1/browser-session \
    -H "x-firmly-app-id: YOUR_APPLICATION_ID" \
    -H "Content-Type: application/json" \
    -d '{"access_token": "EXPIRED_TOKEN"}'
  ```

  ```bash Using Cookie theme={null}
  curl -X POST https://api.firmly.work/api/v1/browser-session \
    -H "x-firmly-app-id: YOUR_APPLICATION_ID" \
    -H "Cookie: fsession_v2=EXPIRED_TOKEN"
  ```
</CodeGroup>

## Using the Access Token

After obtaining the access token, include it in all API requests:

```bash theme={null}
curl -X GET https://api.firmly.work/api/v2/domains/staging.luma.gift/cart \
  -H "x-firmly-authorization: YOUR_ACCESS_TOKEN"
```

## Error Responses

<Accordion title="400 Bad Request">
  Invalid or missing Application ID

  ```json theme={null}
  {
    "error": "InvalidAppId",
    "message": "Application ID is invalid or not found"
  }
  ```
</Accordion>

<Accordion title="401 Unauthorized">
  Expired token cannot be renewed (older than 1 week)

  ```json theme={null}
  {
    "error": "TokenExpired",
    "message": "Token is too old to renew"
  }
  ```
</Accordion>

## Best Practices

1. **Token Refresh**: Implement automatic token refresh before expiration. The authorization token represents the user's device. It should be stored with the user; not with the backend
2. **Error Handling**: Handle token expiration gracefully with retry logic

## Implementation Example

```javascript theme={null}
class FirmlyAuth {
  constructor(appId) {
    this.appId = appId;
    this.token = null;
    this.expiresAt = null;
  }

  async getToken() {
    // Return existing token if still valid
    if (this.token && Date.now() < this.expiresAt) {
      return this.token;
    }

    // Get new token
    const response = await fetch('https://api.firmly.work/api/v1/browser-session', {
      method: 'POST',
      headers: { 'x-firmly-app-id': this.appId }
    });

    const data = await response.json();
    this.token = data.access_token;
    this.expiresAt = data.expires * 1000; // Convert to milliseconds
    
    return this.token;
  }
}
```

## Next Steps

After authentication, you can:

* [Get Cart](/api-reference/cart-management/get-cart) - Retrieve the current cart
* [Browse Products](/api-reference/catalog/get-all-products) - View available products
* [Add to Cart](/api-reference/cart-management/add-line-item) - Add items to cart
