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

# Generate customer portal authentication token

> Generates a secure, time-limited authentication token that grants access to the customer portal. Supports lookup by either Shopify customer ID or customer email address, making it flexible for various integration patterns.

**What This Endpoint Returns:**
An encrypted JWT-like token that authenticates a customer for the subscription management portal, along with token metadata. Unlike the manage-subscription-link endpoint which returns a complete URL, this returns only the token itself.

**Response Components:**

**token (string):**
- Encrypted authentication token
- JWT-style format with cryptographic signature
- Contains customer ID and shop information
- Valid for 2 hours from generation
- Cannot be forged or tampered with

**customerId (long):**
- Shopify customer ID (numeric)
- Useful for verification
- Same ID used to generate token

**Customer Lookup Methods:**

**Option 1: By Customer ID (Recommended)**
```
GET /api/external/v2/customer-portal-token?customerId=12345
```
- Direct lookup by numeric Shopify customer ID
- Can use GraphQL GID format (automatically parsed)
- Fastest and most reliable
- No ambiguity

**Option 2: By Email Address**
```
GET /api/external/v2/customer-portal-token?email=customer@example.com
```
- Searches subscription database for matching email
- Finds associated customer ID automatically
- Useful when customer ID unknown
- Fails if email not found or invalid

**Parameter Validation:**
- Exactly ONE of `customerId` or `email` must be provided
- Providing neither: Returns 400 error
- Providing both: customerId takes precedence
- Email must exist in subscription database

**Token Security:**

**Encryption:**
- Uses HMAC-SHA256 cryptographic signing
- Secret key stored securely on server
- Token includes tamper detection
- Modification invalidates token

**Expiration:**
- Tokens expire exactly 2 hours after generation
- Timestamp embedded in token payload
- Verified on each use
- Cannot be extended

**Scope:**
- Token tied to specific customer
- Token tied to specific shop
- Cannot be used for other customers
- Cannot be used across shops

**Use Cases:**

**1. Custom Portal Implementations:**
- Build custom authentication flows
- Integrate portal into existing apps
- Create native mobile app authentication
- Headless commerce integrations

**2. API-First Architectures:**
- Generate tokens programmatically
- Pass tokens to frontend applications
- Build microservice authentication
- Separate auth from presentation

**3. Single Sign-On (SSO):**
- Authenticate users from existing system
- Bypass password entry
- Seamless portal access
- Cross-platform authentication

**4. Email/SMS Campaigns:**
- Generate tokens for magic links
- Embed in notification emails
- Include in SMS messages
- Create passwordless login links

**5. Customer Support Tools:**
- Generate portal access for support agents
- View customer's portal perspective
- Troubleshoot portal issues
- Assist customers remotely

**Response Format:**
```json
{
  "customerId": 12345,
  "token": "eyJhbGciOiJIUzI1NiJ9.eyJjdXN0b21lcklkIjoxMjM0NSwic2hvcCI6Im15c3RvcmUubXlzaG9waWZ5LmNvbSIsInRpbWVzdGFtcCI6MTcwOTU2MjAwMH0.abc123xyz789"
}
```

**Using the Token:**

**Append to Portal URL:**
```javascript
const { token } = await getCustomerPortalToken(customerId);
const portalUrl = `https://mystore.com/tools/recurring/customer_portal?token=${token}`;
window.location.href = portalUrl;
```

**Store in Session:**
```javascript
// Store for authenticated API calls
sessionStorage.setItem('portalToken', response.token);
sessionStorage.setItem('customerId', response.customerId);

// Use in subsequent requests
fetch('/api/subscription-data', {
  headers: { 'Authorization': `Bearer ${sessionStorage.getItem('portalToken')}` }
});
```

**Mobile App Authentication:**
```javascript
// Generate token server-side
const tokenData = await generateToken(email);

// Send to mobile app
return {
  authToken: tokenData.token,
  customerId: tokenData.customerId,
  expiresIn: 7200 // 2 hours in seconds
};
```

**Important Considerations:**

**Token vs. Full URL:**
- This endpoint: Returns token only
- `/manage-subscription-link` endpoint: Returns complete URL
- Use this for custom implementations
- Use manage-subscription-link for simple email links

**Email Lookup Limitations:**
- Email must exist in subscription database
- Searches only customers with subscriptions
- Won't find customers without subscriptions
- Case-sensitive in some databases

**Customer ID Formats:**
- Accepts numeric ID: `12345`
- Accepts GraphQL GID: `gid://shopify/Customer/12345`
- Automatically extracts numeric portion
- Always stores numeric format

**Best Practices:**

1. **Generate On-Demand**: Create tokens when needed, not in advance
2. **Don't Store Long-Term**: Tokens expire in 2 hours
3. **Use HTTPS**: Always transmit tokens over secure connections
4. **Validate Expiry**: Check token age on frontend
5. **Prefer Customer ID**: Use customerId lookup when available
6. **Handle Errors**: Gracefully handle missing customers

**Security Notes:**
- Treat tokens like passwords
- Don't log tokens in plain text
- Don't expose in URLs if possible (use POST bodies)
- Rotate tokens frequently
- Monitor for suspicious token generation patterns

**Comparison with Other Endpoints:**

**vs. /manage-subscription-link:**
- This: Token only
- That: Complete URL
- Use this for APIs, that for emails

**vs. /subscription-contracts-email-magic-link:**
- This: Returns token
- That: Sends email
- Use this for programmatic access, that for customer notifications

**Authentication:** Requires valid X-API-Key header



## OpenAPI

````yaml /subscription/admin-api-swagger.json get /api/external/v2/customer-portal-token
openapi: 3.0.1
info:
  description: >-
    Comprehensive API documentation for managing subscriptions, payments, and
    related operations. These APIs allow you to programmatically manage
    subscription lifecycles, handle payments, configure products, and integrate
    subscription functionality into your applications.
  title: Admin APIs
  version: 0.0.1
servers:
  - url: https://subscription-admin.appstle.com
security: []
tags:
  - description: >-
      Core APIs for managing the complete subscription lifecycle including
      creation, updates, pausing, resuming, and cancellation of subscriptions.
    name: Subscription Management
  - description: >-
      APIs for managing subscription payment methods, processing payments,
      handling payment retries, and updating billing information.
    name: Subscription Payments
  - description: >-
      APIs for managing subscription contracts including delivery schedules,
      pricing, order notes, billing cycles, and shipping addresses.
    name: Subscription Contracts
  - description: >-
      APIs for managing products within subscriptions including adding,
      removing, updating quantities, and swapping products.
    name: Subscription Products
  - description: >-
      APIs for handling billing operations, payment processing, and financial
      transactions related to subscriptions.
    name: Billing & Payments
  - description: >-
      APIs for managing discounts and promotional codes applied to
      subscriptions.
    name: Subscription Discounts
  - description: >-
      APIs for managing one-time add-on products that can be purchased alongside
      recurring subscription items.
    name: Subscription One-Time Products
  - description: >-
      APIs for managing subscription plans, pricing tiers, and plan
      configurations.
    name: Subscription Plans
  - description: >-
      APIs for managing customizable product boxes and bundles where customers
      can select multiple items.
    name: Build-a-Box & Bundles
  - description: >-
      APIs for managing the product catalog including product information,
      variants, and inventory.
    name: Product Catalog
  - description: >-
      APIs for managing operational settings, configurations, and administrative
      functions.
    name: Operations & Settings
  - description: >-
      APIs powering the customer-facing portal where subscribers can manage
      their own subscriptions.
    name: Customer Portal
  - description: APIs for managing customer information, profiles, and account details.
    name: Customers
  - description: >-
      APIs for retrieving aggregated subscription data, customer subscription
      history, and account-level subscription information.
    name: Subscription Data
  - description: >-
      APIs for managing delivery profiles, shipping rates, free shipping
      configuration, and delivery method options on subscriptions.
    name: Delivery & Shipping
  - description: >-
      APIs for managing storefront customization including custom CSS, theme
      settings, label translations, and merchant-defined widget configuration.
    name: Customization
  - description: >-
      APIs for configuring cancellation flows, retention offers, cancellation
      reason management, and win-back automation.
    name: Customer Retention
paths:
  /api/external/v2/customer-portal-token:
    get:
      tags:
        - Subscription Contracts
        - Customer Portal
      summary: Generate customer portal authentication token
      description: >-
        Generates a secure, time-limited authentication token that grants access
        to the customer portal. Supports lookup by either Shopify customer ID or
        customer email address, making it flexible for various integration
        patterns.


        **What This Endpoint Returns:**

        An encrypted JWT-like token that authenticates a customer for the
        subscription management portal, along with token metadata. Unlike the
        manage-subscription-link endpoint which returns a complete URL, this
        returns only the token itself.


        **Response Components:**


        **token (string):**

        - Encrypted authentication token

        - JWT-style format with cryptographic signature

        - Contains customer ID and shop information

        - Valid for 2 hours from generation

        - Cannot be forged or tampered with


        **customerId (long):**

        - Shopify customer ID (numeric)

        - Useful for verification

        - Same ID used to generate token


        **Customer Lookup Methods:**


        **Option 1: By Customer ID (Recommended)**

        ```

        GET /api/external/v2/customer-portal-token?customerId=12345

        ```

        - Direct lookup by numeric Shopify customer ID

        - Can use GraphQL GID format (automatically parsed)

        - Fastest and most reliable

        - No ambiguity


        **Option 2: By Email Address**

        ```

        GET /api/external/v2/customer-portal-token?email=customer@example.com

        ```

        - Searches subscription database for matching email

        - Finds associated customer ID automatically

        - Useful when customer ID unknown

        - Fails if email not found or invalid


        **Parameter Validation:**

        - Exactly ONE of `customerId` or `email` must be provided

        - Providing neither: Returns 400 error

        - Providing both: customerId takes precedence

        - Email must exist in subscription database


        **Token Security:**


        **Encryption:**

        - Uses HMAC-SHA256 cryptographic signing

        - Secret key stored securely on server

        - Token includes tamper detection

        - Modification invalidates token


        **Expiration:**

        - Tokens expire exactly 2 hours after generation

        - Timestamp embedded in token payload

        - Verified on each use

        - Cannot be extended


        **Scope:**

        - Token tied to specific customer

        - Token tied to specific shop

        - Cannot be used for other customers

        - Cannot be used across shops


        **Use Cases:**


        **1. Custom Portal Implementations:**

        - Build custom authentication flows

        - Integrate portal into existing apps

        - Create native mobile app authentication

        - Headless commerce integrations


        **2. API-First Architectures:**

        - Generate tokens programmatically

        - Pass tokens to frontend applications

        - Build microservice authentication

        - Separate auth from presentation


        **3. Single Sign-On (SSO):**

        - Authenticate users from existing system

        - Bypass password entry

        - Seamless portal access

        - Cross-platform authentication


        **4. Email/SMS Campaigns:**

        - Generate tokens for magic links

        - Embed in notification emails

        - Include in SMS messages

        - Create passwordless login links


        **5. Customer Support Tools:**

        - Generate portal access for support agents

        - View customer's portal perspective

        - Troubleshoot portal issues

        - Assist customers remotely


        **Response Format:**

        ```json

        {
          "customerId": 12345,
          "token": "eyJhbGciOiJIUzI1NiJ9.eyJjdXN0b21lcklkIjoxMjM0NSwic2hvcCI6Im15c3RvcmUubXlzaG9waWZ5LmNvbSIsInRpbWVzdGFtcCI6MTcwOTU2MjAwMH0.abc123xyz789"
        }

        ```


        **Using the Token:**


        **Append to Portal URL:**

        ```javascript

        const { token } = await getCustomerPortalToken(customerId);

        const portalUrl =
        `https://mystore.com/tools/recurring/customer_portal?token=${token}`;

        window.location.href = portalUrl;

        ```


        **Store in Session:**

        ```javascript

        // Store for authenticated API calls

        sessionStorage.setItem('portalToken', response.token);

        sessionStorage.setItem('customerId', response.customerId);


        // Use in subsequent requests

        fetch('/api/subscription-data', {
          headers: { 'Authorization': `Bearer ${sessionStorage.getItem('portalToken')}` }
        });

        ```


        **Mobile App Authentication:**

        ```javascript

        // Generate token server-side

        const tokenData = await generateToken(email);


        // Send to mobile app

        return {
          authToken: tokenData.token,
          customerId: tokenData.customerId,
          expiresIn: 7200 // 2 hours in seconds
        };

        ```


        **Important Considerations:**


        **Token vs. Full URL:**

        - This endpoint: Returns token only

        - `/manage-subscription-link` endpoint: Returns complete URL

        - Use this for custom implementations

        - Use manage-subscription-link for simple email links


        **Email Lookup Limitations:**

        - Email must exist in subscription database

        - Searches only customers with subscriptions

        - Won't find customers without subscriptions

        - Case-sensitive in some databases


        **Customer ID Formats:**

        - Accepts numeric ID: `12345`

        - Accepts GraphQL GID: `gid://shopify/Customer/12345`

        - Automatically extracts numeric portion

        - Always stores numeric format


        **Best Practices:**


        1. **Generate On-Demand**: Create tokens when needed, not in advance

        2. **Don't Store Long-Term**: Tokens expire in 2 hours

        3. **Use HTTPS**: Always transmit tokens over secure connections

        4. **Validate Expiry**: Check token age on frontend

        5. **Prefer Customer ID**: Use customerId lookup when available

        6. **Handle Errors**: Gracefully handle missing customers


        **Security Notes:**

        - Treat tokens like passwords

        - Don't log tokens in plain text

        - Don't expose in URLs if possible (use POST bodies)

        - Rotate tokens frequently

        - Monitor for suspicious token generation patterns


        **Comparison with Other Endpoints:**


        **vs. /manage-subscription-link:**

        - This: Token only

        - That: Complete URL

        - Use this for APIs, that for emails


        **vs. /subscription-contracts-email-magic-link:**

        - This: Returns token

        - That: Sends email

        - Use this for programmatic access, that for customer notifications


        **Authentication:** Requires valid X-API-Key header
      operationId: getCustomerPortalToken
      parameters:
        - description: API Key (Deprecated - Use Header X-API-Key instead)
          in: query
          name: api_key
          required: false
          schema:
            type: string
        - in: header
          name: X-API-Key
          required: false
          schema:
            type: string
        - description: Customer ID
          in: query
          name: customerId
          required: false
          schema:
            type: string
        - description: Customer email
          in: query
          name: email
          required: false
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              examples:
                Token Response:
                  description: Token Response
                  value:
                    customerId: 12345
                    token: >-
                      eyJhbGciOiJIUzI1NiJ9.eyJjdXN0b21lcklkIjoxMjM0NSwic2hvcCI6Im15c3RvcmUubXlzaG9waWZ5LmNvbSIsInRpbWVzdGFtcCI6MTcwOTU2MjAwMH0.abc123xyz789
              schema:
                $ref: '#/components/schemas/CustomerTokenInfo'
          description: Successfully generated customer portal token
        '400':
          content:
            application/json:
              examples:
                Customer Not Found:
                  description: Customer Not Found
                  value:
                    detail: Customer Id or Email does not exist
                    status: 400
                    title: Customer not found
                    type: https://example.com/errors/bad-request
                Missing Parameters:
                  description: Missing Parameters
                  value:
                    detail: Customer Id or Email does not exist
                    status: 400
                    title: Missing required parameter
                    type: https://example.com/errors/bad-request
          description: Bad request - Missing parameters or invalid customer
        '401':
          content:
            application/json:
              example:
                detail: Valid X-API-Key header is required
                status: 401
                title: Authentication required
                type: https://example.com/errors/unauthorized
          description: Authentication required
        '403':
          content:
            application/json:
              example:
                detail: Customer does not belong to your shop
                status: 403
                title: Access denied
                type: https://example.com/errors/forbidden
          description: Forbidden - Customer does not belong to authenticated shop
components:
  schemas:
    CustomerTokenInfo:
      properties:
        appstleExternalToken:
          type: string
        customerId:
          format: int64
          type: integer
        token:
          type: string
      type: object

````