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

# Create business-scoped access token

> Create a business-scoped JWT token for accessing business-specific endpoints. Requires a valid partner (unscoped) Bearer token in the Authorization header. Use the BearerUnscoped option in Swagger UI.

## What is a Business-Scoped Token?

A **business-scoped token** is a JWT that grants access to a specific business's data. It's required for endpoints that operate on business-level resources (customers, invoices, bills, etc.).

### Why Two Types of Tokens?

**Partner Token (Unscoped):**

* Obtained from `/oauth2/token/` using your Partner UUID + API Key
* Used for **partner-level operations**: listing businesses, creating new businesses
* Can access multiple businesses you own
* **Limited scope** - cannot access business-specific resources

**Business Token (Scoped):**

* Obtained from `/{business_id}/oauth2/token/` using a partner token
* Used for **business-specific operations**: managing customers, invoices, bills, payments
* **Locked to one business** - can only access that business's data
* **Required for most API endpoints**

### When Do You Need This?

**Use business-scoped tokens for:**

* Managing customers for a specific business
* Creating invoices or bills
* Processing payments
* Any endpoint with `/businesses/{business_id}/` in the path

**Use partner tokens for:**

* Listing all businesses you manage
* Creating new businesses
* Partner-level reporting

### How It Works

**Step 1:** Get partner token (unscoped)

```bash theme={null}
# First, get your partner-level token
curl -X POST https://sandbox.thredfi.com/v1/platform/oauth2/token/ \
  -H "Authorization: Basic $(echo -n 'PARTNER_UUID:API_KEY' | base64)" \
  -d "grant_type=client_credentials"

# Response: { "access_token": "partner_token_here..." }
```

**Step 2:** Exchange for business-scoped token

```bash theme={null}
# Then, get a business-specific token
curl -X POST https://sandbox.thredfi.com/v1/platform/BUSINESS_ID/oauth2/token/ \
  -H "Authorization: Bearer partner_token_here"

# Response: { "access_token": "business_scoped_token_here..." }
```

**Step 3:** Use business token for operations

```bash theme={null}
# Now you can access business resources
curl https://sandbox.thredfi.com/v1/platform/businesses/BUSINESS_ID/customers/ \
  -H "Authorization: Bearer business_scoped_token_here"
```

### Code Examples

<CodeGroup>
  ```python Python theme={null}
  import requests
  import base64

  # Step 1: Get partner token
  partner_uuid = "123e4567-e89b-12d3-a456-426614174000"
  api_key = "sk_live_abc123xyz789"
  credentials = f"{partner_uuid}:{api_key}"
  encoded = base64.b64encode(credentials.encode()).decode()

  partner_response = requests.post(
      "https://sandbox.thredfi.com/v1/platform/oauth2/token/",
      headers={"Authorization": f"Basic {encoded}"},
      data={"grant_type": "client_credentials"}
  )
  partner_token = partner_response.json()["access_token"]

  # Step 2: Get business-scoped token
  business_id = "456e7890-e89b-12d3-a456-426614174111"
  business_response = requests.post(
      f"https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/",
      headers={"Authorization": f"Bearer {partner_token}"}
  )
  business_token = business_response.json()["access_token"]

  # Step 3: Use business token to access resources
  customers = requests.get(
      f"https://sandbox.thredfi.com/v1/platform/businesses/{business_id}/customers/",
      headers={"Authorization": f"Bearer {business_token}"}
  )
  print(customers.json())
  ```

  ```javascript JavaScript/Node.js theme={null}
  const axios = require('axios');

  async function authenticateAndFetchCustomers() {
    // Step 1: Get partner token
    const partnerUuid = '123e4567-e89b-12d3-a456-426614174000';
    const apiKey = 'sk_live_abc123xyz789';
    const encoded = Buffer.from(`${partnerUuid}:${apiKey}`).toString('base64');

    const partnerResponse = await axios.post(
      'https://sandbox.thredfi.com/v1/platform/oauth2/token/',
      new URLSearchParams({ grant_type: 'client_credentials' }),
      { headers: { 'Authorization': `Basic ${encoded}` } }
    );
    const partnerToken = partnerResponse.data.access_token;

    // Step 2: Get business-scoped token
    const businessId = '456e7890-e89b-12d3-a456-426614174111';
    const businessResponse = await axios.post(
      `https://sandbox.thredfi.com/v1/platform/${businessId}/oauth2/token/`,
      {},
      { headers: { 'Authorization': `Bearer ${partnerToken}` } }
    );
    const businessToken = businessResponse.data.access_token;

    // Step 3: Use business token to access resources
    const customers = await axios.get(
      `https://sandbox.thredfi.com/v1/platform/businesses/${businessId}/customers/`,
      { headers: { 'Authorization': `Bearer ${businessToken}` } }
    );

    console.log(customers.data);
  }
  ```

  ```bash cURL theme={null}
  # Step 1: Get partner token
  PARTNER_TOKEN=$(curl -X POST https://sandbox.thredfi.com/v1/platform/oauth2/token/ \
    -H "Authorization: Basic $(echo -n 'YOUR_PARTNER_UUID:YOUR_API_KEY' | base64)" \
    -d "grant_type=client_credentials" | jq -r '.access_token')

  # Step 2: Get business-scoped token
  BUSINESS_ID="456e7890-e89b-12d3-a456-426614174111"
  BUSINESS_TOKEN=$(curl -X POST https://sandbox.thredfi.com/v1/platform/$BUSINESS_ID/oauth2/token/ \
    -H "Authorization: Bearer $PARTNER_TOKEN" | jq -r '.access_token')

  # Step 3: Use business token
  curl https://sandbox.thredfi.com/v1/platform/businesses/$BUSINESS_ID/customers/ \
    -H "Authorization: Bearer $BUSINESS_TOKEN"
  ```
</CodeGroup>

### Security Note

Business-scoped tokens are **more secure** for business operations because:

* They can only access one specific business
* If compromised, the blast radius is limited to that single business
* They can be revoked independently without affecting other businesses

### Token Lifecycle

1. **Partner token** is long-lived (typically 24 hours)
2. **Business token** is also long-lived (typically 24 hours)
3. Both can be refreshed by re-authenticating
4. Store securely and never expose in client-side code


## OpenAPI

````yaml POST /v1/platform/{business_id}/oauth2/token/
openapi: 3.0.3
info:
  title: Thredfi Accounting Platform API
  version: 1.0.0
  description: >-
    Comprehensive API for accounting, invoice management, open banking, and
    intelligence services.
servers: []
security: []
paths:
  /v1/platform/{business_id}/oauth2/token/:
    post:
      tags:
        - Oauth2 authentication - Unscoped and Scoped
      summary: Create business-scoped access token
      description: >-
        Create a business-scoped JWT token for accessing business-specific
        endpoints. Requires a valid partner (unscoped) Bearer token in the
        Authorization header. Use the BearerUnscoped option in Swagger UI.
      operationId: create_business_scoped_token
      parameters:
        - in: path
          name: business_id
          schema:
            type: string
            format: uuid
          required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessTokenResponse'
              examples:
                BusinessTokenResponse:
                  value:
                    access_token: >-
                      eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhMWIyYzNkNC01Njc4LTkwYWItY2RlZi0xMjM0NTY3ODkwYWIiLCJidXNpbmVzc19pZCI6IjNjOTBjM2NjLTBkNDQtNGI1MC04ODg4LThkZDI1NzM2MDUyYSIsImlhdCI6MTcwOTgyMTIwMCwiZXhwIjoxNzA5ODI0ODAwfQ.example
                    token_type: Bearer
                    expires_in: 3600
                    scope: business_access
                    business_id: 3c90c3cc-0d44-4b50-8888-8dd25736052a
                  summary: Business Token Response
          description: ''
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuth2ErrorResponse'
          description: ''
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuth2ErrorResponse'
          description: ''
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuth2ErrorResponse'
          description: ''
      security:
        - PartnerJWT: []
        - BasicAuth: []
        - BearerUnscoped: []
        - BearerBusinessScoped: []
components:
  schemas:
    BusinessTokenResponse:
      type: object
      description: Serializer for business-scoped token response
      properties:
        access_token:
          type: string
          description: Business-scoped JWT Bearer token
        token_type:
          type: string
          default: Bearer
          description: Token type (always 'Bearer')
        expires_in:
          type: integer
          description: Token expiration time in seconds
        scope:
          type: string
          description: Token scope (always 'business_access')
        business_id:
          type: string
          format: uuid
          description: ID of the business this token is scoped to
      required:
        - access_token
        - business_id
        - expires_in
        - scope
    OAuth2ErrorResponse:
      type: object
      description: Serializer for OAuth2 error response
      properties:
        error:
          type: string
          description: Error code (e.g., 'invalid_client', 'unsupported_grant_type')
        error_description:
          type: string
          description: Human-readable error description
      required:
        - error
        - error_description
  securitySchemes:
    PartnerJWT:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Partner-level JWT token (unscoped). Token payload includes `partner_id`.
        Business access is validated via partner ownership. Format: `Bearer
        <your-jwt-token>`


        **Use this for**: Multi-business operations where the business_id is
        specified in the URL and partner has access to multiple businesses.
    BasicAuth:
      type: http
      scheme: basic
      description: >-
        Basic authentication for OAuth2 token endpoint. Use partner_uuid:api_key
        as username:password. Example: Authorization: Basic
        base64(partner_uuid:api_key)
    BearerUnscoped:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Partner (unscoped) JWT Bearer token. Obtain via POST
        /v1/platform/oauth2/token with Basic auth (partner_uuid:api_key). Use
        header: Authorization: Bearer {access_token}
    BearerBusinessScoped:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Business-scoped JWT Bearer token. Obtain via POST
        /v1/platform/{business_id}/oauth2/token/ using a partner Bearer token.
        Only valid for endpoints whose URL contains that business_id.

````