> ## 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 access link by customer ID or email

> Generates a secure, time-limited magic link that allows customers to access their subscription management portal. This endpoint supports lookup by either customer ID or email address, making it flexible for different integration scenarios.

**Key Features:**
- **Dual Lookup**: Find customer by ID or email
- **Auto Customer Discovery**: Automatically finds customer from email
- **Secure Tokens**: Encrypted tokens with 2-hour expiration
- **Custom Domains**: Supports shop's public domain
- **Zero-Auth Access**: Customers don't need passwords

**Customer Lookup Logic:**

**Option 1: By Customer ID (Preferred)**
```
GET /api/external/v2/manage-subscription-link?customerId=12345
```
- Direct lookup by Shopify customer ID
- Fastest and most reliable method
- No ambiguity

**Option 2: By Email**
```
GET /api/external/v2/manage-subscription-link?emailId=customer@example.com
```
- Searches for customer by email in subscription database
- Finds customer ID automatically
- If not found: Returns error

**Validation Rules:**
- Either `customerId` OR `emailId` must be provided
- Cannot provide both (customerId takes precedence)
- Email must match a customer with subscriptions
- Customer must belong to authenticated shop

**Token Generation:**

**Token Contents:**
- Encrypted customer ID
- Shop domain
- Generation timestamp
- Expiration time (2 hours)

**Security Features:**
- Cryptographically secure encryption
- Cannot be forged or modified
- Automatic expiration after 2 hours
- Single-use recommended (though not enforced)
- Tied to specific shop and customer

**Generated URL Structure:**
```
https://[shop-domain]/[manage-subscriptions-path]?token=[encrypted-token]
```

**Example URLs:**
```
https://mystore.com/tools/recurring/customer_portal?token=eyJhbGc...
https://shop.myshopify.com/tools/recurring/customer_portal?token=eyJhbGc...
```

**Use Cases:**

**1. Email Campaigns:**
- Add "Manage Subscription" button to transactional emails
- Include in billing reminder emails
- Send in order confirmation emails
- Add to marketing campaigns

**2. Customer Support:**
- Provide customers quick portal access
- Avoid "forgot password" issues
- Enable instant self-service
- Reduce support ticket volume

**3. Post-Purchase Flows:**
- Thank you page portal links
- First order welcome emails
- Onboarding email sequences
- Re-engagement campaigns

**4. Account Management:**
- SMS notifications with portal links
- Push notification deep links
- Customer dashboard integrations
- Third-party app integrations

**Response Format:**
```json
{
  "manageSubscriptionLink": "https://mystore.com/tools/recurring/customer_portal?token=eyJhbGciOiJIUzI1NiJ9...",
  "tokenExpirationTime": "2024-03-15T14:30:00Z"
}
```

**Response Fields:**
- `manageSubscriptionLink`: Complete URL ready to use
- `tokenExpirationTime`: ISO 8601 timestamp when token expires

**Integration Examples:**

**Email Template:**
```javascript
const response = await fetch(
  `/api/external/v2/manage-subscription-link?emailId=${customerEmail}`,
  { headers: { 'X-API-Key': 'your-key' } }
).then(r => r.json());

const emailHtml = `
  <p>Hi ${customerName},</p>
  <p>Manage your subscription:</p>
  <a href="${response.manageSubscriptionLink}">Manage Subscription</a>
  <p><small>Link expires ${formatDate(response.tokenExpirationTime)}</small></p>
`;
```

**SMS Notification:**
```javascript
const { manageSubscriptionLink } = await getPortalLink(customerId);
const shortUrl = await shortenUrl(manageSubscriptionLink);

await sendSMS(customerPhone, 
  `Your subscription ships tomorrow! Manage it here: ${shortUrl}`
);
```

**Important Considerations:**

**Token Expiration:**
- Tokens expire after exactly 2 hours
- Generate new token if expired
- Don't store tokens long-term
- Best practice: Generate on-demand

**Domain Selection:**
- Uses shop's `publicDomain` if configured
- Falls back to Shopify domain (.myshopify.com)
- Respects custom domain settings
- Maintains brand consistency

**Customer Lookup Errors:**
- Email not found: Returns 400 error
- Invalid customer ID: Returns error
- No parameters provided: Returns 400
- Both parameters provided: Uses customerId

**Security Notes:**
- Tokens cannot be used across different shops
- Cannot be used for different customers
- Tampering invalidates token
- Consider rate limiting token generation

**Best Practices:**

1. **Generate On-Demand**: Create tokens when needed, not in advance
2. **Use HTTPS**: Always serve links over HTTPS
3. **Show Expiry**: Inform customers when link expires
4. **URL Shortening**: Use URL shorteners for SMS/print materials
5. **Track Usage**: Monitor which emails drive portal visits
6. **Prefer Customer ID**: Use customerId when available for faster lookup

**Comparison with /manage-subscription-link/{customerId}:**
- This endpoint: Flexible lookup (ID or email)
- Path parameter version: Customer ID only
- Both generate identical tokens
- Use this for email-based flows

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



## OpenAPI

````yaml /subscription/admin-api-swagger.json get /api/external/v2/manage-subscription-link
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/manage-subscription-link:
    get:
      tags:
        - Customers
        - Subscription Contracts
      summary: Generate customer portal access link by customer ID or email
      description: >-
        Generates a secure, time-limited magic link that allows customers to
        access their subscription management portal. This endpoint supports
        lookup by either customer ID or email address, making it flexible for
        different integration scenarios.


        **Key Features:**

        - **Dual Lookup**: Find customer by ID or email

        - **Auto Customer Discovery**: Automatically finds customer from email

        - **Secure Tokens**: Encrypted tokens with 2-hour expiration

        - **Custom Domains**: Supports shop's public domain

        - **Zero-Auth Access**: Customers don't need passwords


        **Customer Lookup Logic:**


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

        ```

        GET /api/external/v2/manage-subscription-link?customerId=12345

        ```

        - Direct lookup by Shopify customer ID

        - Fastest and most reliable method

        - No ambiguity


        **Option 2: By Email**

        ```

        GET
        /api/external/v2/manage-subscription-link?emailId=customer@example.com

        ```

        - Searches for customer by email in subscription database

        - Finds customer ID automatically

        - If not found: Returns error


        **Validation Rules:**

        - Either `customerId` OR `emailId` must be provided

        - Cannot provide both (customerId takes precedence)

        - Email must match a customer with subscriptions

        - Customer must belong to authenticated shop


        **Token Generation:**


        **Token Contents:**

        - Encrypted customer ID

        - Shop domain

        - Generation timestamp

        - Expiration time (2 hours)


        **Security Features:**

        - Cryptographically secure encryption

        - Cannot be forged or modified

        - Automatic expiration after 2 hours

        - Single-use recommended (though not enforced)

        - Tied to specific shop and customer


        **Generated URL Structure:**

        ```

        https://[shop-domain]/[manage-subscriptions-path]?token=[encrypted-token]

        ```


        **Example URLs:**

        ```

        https://mystore.com/tools/recurring/customer_portal?token=eyJhbGc...

        https://shop.myshopify.com/tools/recurring/customer_portal?token=eyJhbGc...

        ```


        **Use Cases:**


        **1. Email Campaigns:**

        - Add "Manage Subscription" button to transactional emails

        - Include in billing reminder emails

        - Send in order confirmation emails

        - Add to marketing campaigns


        **2. Customer Support:**

        - Provide customers quick portal access

        - Avoid "forgot password" issues

        - Enable instant self-service

        - Reduce support ticket volume


        **3. Post-Purchase Flows:**

        - Thank you page portal links

        - First order welcome emails

        - Onboarding email sequences

        - Re-engagement campaigns


        **4. Account Management:**

        - SMS notifications with portal links

        - Push notification deep links

        - Customer dashboard integrations

        - Third-party app integrations


        **Response Format:**

        ```json

        {
          "manageSubscriptionLink": "https://mystore.com/tools/recurring/customer_portal?token=eyJhbGciOiJIUzI1NiJ9...",
          "tokenExpirationTime": "2024-03-15T14:30:00Z"
        }

        ```


        **Response Fields:**

        - `manageSubscriptionLink`: Complete URL ready to use

        - `tokenExpirationTime`: ISO 8601 timestamp when token expires


        **Integration Examples:**


        **Email Template:**

        ```javascript

        const response = await fetch(
          `/api/external/v2/manage-subscription-link?emailId=${customerEmail}`,
          { headers: { 'X-API-Key': 'your-key' } }
        ).then(r => r.json());


        const emailHtml = `
          <p>Hi ${customerName},</p>
          <p>Manage your subscription:</p>
          <a href="${response.manageSubscriptionLink}">Manage Subscription</a>
          <p><small>Link expires ${formatDate(response.tokenExpirationTime)}</small></p>
        `;

        ```


        **SMS Notification:**

        ```javascript

        const { manageSubscriptionLink } = await getPortalLink(customerId);

        const shortUrl = await shortenUrl(manageSubscriptionLink);


        await sendSMS(customerPhone, 
          `Your subscription ships tomorrow! Manage it here: ${shortUrl}`
        );

        ```


        **Important Considerations:**


        **Token Expiration:**

        - Tokens expire after exactly 2 hours

        - Generate new token if expired

        - Don't store tokens long-term

        - Best practice: Generate on-demand


        **Domain Selection:**

        - Uses shop's `publicDomain` if configured

        - Falls back to Shopify domain (.myshopify.com)

        - Respects custom domain settings

        - Maintains brand consistency


        **Customer Lookup Errors:**

        - Email not found: Returns 400 error

        - Invalid customer ID: Returns error

        - No parameters provided: Returns 400

        - Both parameters provided: Uses customerId


        **Security Notes:**

        - Tokens cannot be used across different shops

        - Cannot be used for different customers

        - Tampering invalidates token

        - Consider rate limiting token generation


        **Best Practices:**


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

        2. **Use HTTPS**: Always serve links over HTTPS

        3. **Show Expiry**: Inform customers when link expires

        4. **URL Shortening**: Use URL shorteners for SMS/print materials

        5. **Track Usage**: Monitor which emails drive portal visits

        6. **Prefer Customer ID**: Use customerId when available for faster
        lookup


        **Comparison with /manage-subscription-link/{customerId}:**

        - This endpoint: Flexible lookup (ID or email)

        - Path parameter version: Customer ID only

        - Both generate identical tokens

        - Use this for email-based flows


        **Authentication:** Requires valid X-API-Key header
      operationId: getManageSubscriptionLinkv3
      parameters:
        - in: query
          name: api_key
          required: false
          schema:
            type: string
        - in: header
          name: X-API-Key
          required: false
          schema:
            type: string
        - in: query
          name: customerId
          required: false
          schema:
            format: int64
            type: integer
        - in: query
          name: emailId
          required: false
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              examples:
                Success Response:
                  description: Success Response
                  value:
                    manageSubscriptionLink: >-
                      https://mystore.com/tools/recurring/customer_portal?token=eyJhbGciOiJIUzI1NiJ9.eyJjdXN0b21lcklkIjoxMjM0NSwic2hvcCI6Im15c3RvcmUubXlzaG9waWZ5LmNvbSIsInRpbWVzdGFtcCI6MTcwOTU2MjAwMH0.abc123xyz
                    tokenExpirationTime: '2024-03-15T14:30:00Z'
              schema:
                $ref: '#/components/schemas/TokenDetails'
          description: Successfully generated manage subscription link
        '400':
          content:
            application/json:
              examples:
                Customer Not Found:
                  description: Customer Not Found
                  value:
                    detail: >-
                      Customer not found for the provided email:
                      customer@example.com
                    status: 400
                    title: Customer not found
                    type: https://example.com/errors/bad-request
                Missing Parameters:
                  description: Missing Parameters
                  value:
                    detail: Either customerId or emailId must be provided.
                    status: 400
                    title: Missing required parameter
                    type: https://example.com/errors/bad-request
          description: Bad request - Missing parameters or customer not found
        '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
        '500':
          content:
            application/json:
              example:
                detail: Failed to generate customer portal token
                status: 500
                title: Token generation failed
                type: https://example.com/errors/internal-error
          description: Internal server error
components:
  schemas:
    TokenDetails:
      properties:
        manageSubscriptionLink:
          type: string
        tokenExpirationTime:
          format: date-time
          type: string
      type: object

````