# Customers APIs for managing customer information, profiles, and account details. ## Get customer details with subscriptions - [GET /api/external/v2/subscription-customers/{id}](https://developers.subscription.appstle.com/external-api-swagger/customers/getsubscriptioncustomerv2.md): Retrieves comprehensive customer information including their subscription contracts. This endpoint provides customer profile data along with a paginated list of their active and historical subscriptions. Key Features: - Customer profile information (name, email, phone, addresses) - Complete subscription history with pagination - Payment method details - Customer account state and metadata - Order history related to subscriptions - Customer tags and notes Subscription Data Included: - All subscription contracts (active, paused, cancelled) - Contract details with line items - Billing and delivery policies - Next billing dates and amounts - Applied discounts Pagination: - Subscription contracts are paginated - Default page size varies by Shopify plan - Use cursor for subsequent pages - Cursor-based pagination ensures consistency Use Cases: - Customer service representatives viewing customer details - Integration with CRM systems - Customer analytics and reporting - Subscription management interfaces - Billing reconciliation Important Notes: - Customer ID is numeric (without gid:// prefix) - Returns null if customer not found - Includes both active and inactive subscriptions - Payment methods may be masked for security Authentication: Requires valid X-API-Key header ## Get valid subscription contract IDs for a customer - [GET /api/external/v2/subscription-customers/valid/{customerId}](https://developers.subscription.appstle.com/external-api-swagger/customers/getvalidsubscriptioncustomerv2.md): Retrieves a set of all valid (active, paused, or otherwise non-deleted) subscription contract IDs for a specific customer. This endpoint returns only the contract IDs without detailed subscription information, making it ideal for quick lookups and validation checks. What Are Valid Subscription Contracts? Valid contracts are subscriptions that exist in the system and haven't been permanently deleted. This includes subscriptions in all states except those that have been hard-deleted or hidden from the system. The contract IDs returned represent subscriptions that can be queried, modified, or managed through other API endpoints. Contract States Included: Active States: - ACTIVE - Currently active and billing recurring subscriptions - PAUSED - Temporarily paused subscriptions (customer can resume) Inactive States: - CANCELLED - Cancelled subscriptions (retained for historical data) - EXPIRED - Subscriptions that reached their max cycle limit - FAILED - Subscriptions with payment failures (may be in dunning) Excluded: - Hard-deleted subscription records - Hidden subscriptions (marked for cleanup) - Subscriptions from test/development that were purged Use Cases: 1. Customer Portal: - Check if customer has any subscriptions before showing portal - Display subscription count in dashboard - Validate customer access to subscription management 2. Integration & Automation: - Pre-flight check before bulk operations - Verify customer has subscriptions before sending emails - Filter customers for targeted campaigns (has active subscriptions) 3. Validation & Security: - Verify a specific contract ID belongs to a customer - Validate user permissions before showing subscription details - Check authorization for subscription modification requests 4. Analytics & Reporting: - Count total subscriptions per customer - Identify customers with multiple subscriptions - Build customer segmentation based on subscription count Response Format: Returns a Set containing Shopify subscription contract IDs. json [123456789, 123456790, 123456791] Set Properties: - Unique values: No duplicate contract IDs - Unordered: IDs are not in any specific order - Numeric: IDs are Long integers (not GraphQL GIDs) Common Response Scenarios: Customer with multiple subscriptions: json [5234567890, 5234567891, 5234567892, 5234567893] Customer with single subscription: json [5234567890] Customer with no subscriptions: json [] Integration Examples: Example 1: Check if customer has subscriptions javascript const contractIds = await fetch('/api/external/v2/subscription-customers/valid/12345', { headers: { 'X-API-Key': 'your-api-key' } }).then(r => r.json()); if (contractIds.length > 0) { console.log(Customer has ${contractIds.length} subscriptions); // Show customer portal } else { console.log('Customer has no subscriptions'); // Redirect to create subscription page } Example 2: Validate contract ownership javascript const customerId = 12345; const contractIdToVerify = 5234567890; const validContracts = await fetch(/api/external/v2/subscription-customers/valid/${customerId}, { headers: { 'X-API-Key': 'your-api-key' } }).then(r => r.json()); if (validContracts.includes(contractIdToVerify)) { console.log('Customer owns this contract - allowing access'); // Proceed with subscription modification } else { console.log('Unauthorized - contract does not belong to customer'); // Return 403 Forbidden } Performance Characteristics: Fast Response: - Lightweight query (returns only IDs, not full subscription data) - Typical response time: 50-200ms - Suitable for real-time validation checks Scalability: - Efficient even for customers with 100+ subscriptions - Database query uses indexed customer ID field - Minimal network payload (just array of numbers) Important Notes: Contract ID Format: - Returns numeric Shopify contract IDs (e.g., 5234567890) - NOT Shopify GraphQL GIDs (e.g., gid://shopify/SubscriptionContract/...) - Use these IDs with other Appstle API endpoints Data Freshness: - Returns data from Appstle database (not real-time Shopify query) - Data is updated via webhooks (typically < 1 second lag) - If data seems stale, use sync endpoint to refresh Empty Response: - Empty array [] means customer has no valid subscriptions - This is NOT an error - it's a valid response - Returns 200 OK with empty array (not 404) Security & Authorization: - Customer ID is validated against authenticated shop - Cannot query customers from other shops - API key must have customer read permissions Best Practices: 1. Use for Validation: Perfect for quick ownership/existence checks 2. Cache Locally: Cache results briefly to reduce API calls 3. Check Empty Array: Always handle empty array case gracefully 4. Combine with Details: Use this for initial check, then fetch full details if needed 5. Avoid Polling: Don't poll this endpoint repeatedly - use webhooks for updates When to Use vs. Other Endpoints: Use this endpoint when you: - Need just the contract IDs (not full subscription details) - Want to validate a customer has subscriptions - Need to verify contract ownership for authorization - Want fast, lightweight responses Use subscription-customers-detail endpoint when you: - Need full subscription details (status, products, billing dates, etc.) - Want to display subscription information to users - Need to make decisions based on subscription state Related Endpoints: - GET /api/external/v2/subscription-customers-detail/valid/{customerId} - Get full subscription details - GET /api/external/v2/subscription-contract-details - Query subscriptions with filters - GET /api/external/v2/subscription-contracts/contract-external/{contractId} - Get single contract details Authentication: Requires valid X-API-Key header or api_key parameter (deprecated) ## Sync customer subscription details from Shopify - [GET /api/external/v2/subscription-customers/sync-info/{customerId}](https://developers.subscription.appstle.com/external-api-swagger/customers/synccustomerinfo.md): Synchronizes customer subscription information from Shopify to the Appstle subscription system. This endpoint fetches the latest customer data from Shopify and updates the local database to ensure data consistency across platforms. What Does This Endpoint Do? This endpoint triggers a synchronization process that pulls customer subscription data from Shopify's GraphQL API and updates the Appstle subscription database with the latest information. It ensures that customer details, subscription statuses, and associated metadata are current and accurate. Sync Process: 1. Data Retrieval: Fetches customer subscription data from Shopify using their GraphQL API 2. Validation: Validates the retrieved data against existing records 3. Update: Updates customer subscription details in Appstle database 4. Reconciliation: Reconciles any discrepancies between Shopify and Appstle data 5. Logging: Logs all sync activities for audit trail What Gets Synchronized: Customer Information: - Customer ID and Shopify GraphQL ID - Customer name and email address - Customer tags and metadata - Customer acceptance status - Marketing preferences Subscription Details: - Active subscription contracts - Subscription statuses (ACTIVE, PAUSED, CANCELLED, EXPIRED) - Next billing dates - Billing interval and delivery interval - Subscription line items (products and variants) - Pricing and discounts Payment Information: - Associated payment methods - Payment instrument status - Billing address details Delivery Information: - Shipping address details - Delivery method and profile - Delivery preferences Use Cases: 1. Data Consistency: - Resolve data discrepancies between Shopify and Appstle - Update customer information after changes in Shopify admin - Sync subscription modifications made directly in Shopify 2. Troubleshooting: - Fix sync issues for specific customers - Recover from webhook delivery failures - Debug customer portal display issues 3. Migration & Integration: - Initial data sync after app installation - Re-sync after system maintenance or updates - Integration testing and validation 4. Customer Support: - Refresh customer data when assisting with support tickets - Verify latest subscription status during customer inquiries - Update data after manual changes in Shopify When to Use This Endpoint: Recommended Scenarios: - Customer reports incorrect subscription data in portal - After making manual changes to subscriptions in Shopify admin - When troubleshooting webhook sync failures - Before running bulk operations on customer subscriptions - During migration or data reconciliation processes Avoid Using For: - Real-time data refresh (webhooks handle this automatically) - Frequent polling (use webhooks instead to avoid rate limits) - Bulk syncs of many customers (use batch endpoints or scheduled jobs) Sync Behavior: Synchronous Operation: - Endpoint blocks until sync completes - Returns void on success - Throws exception on failure Data Precedence: - Shopify data is always treated as source of truth - Local Appstle data is overwritten with Shopify values - Custom Appstle-specific fields are preserved Error Handling: - Invalid customer ID: Returns 400 Bad Request - Customer not found in Shopify: Returns 404 Not Found - Shopify API errors: Returns 502 Bad Gateway - Rate limit exceeded: Returns 429 Too Many Requests Important Considerations: Performance: - Sync duration depends on number of subscriptions (typically 1-5 seconds) - May timeout for customers with 100+ active subscriptions - Consider using asynchronous sync for high-volume customers Rate Limiting: - Subject to Shopify GraphQL API rate limits - Frequent calls may exhaust rate limit budget - Use webhooks for real-time sync instead of polling this endpoint Data Integrity: - Always creates audit log entries for tracking - Preserves historical data and activity logs - Does not delete local-only data (e.g., custom notes) Best Practices: 1. Use Sparingly: Rely on webhooks for automatic sync; use this only when needed 2. Check Logs: Review activity logs after sync to verify changes 3. Validate Results: Query customer data after sync to confirm updates 4. Handle Errors: Implement retry logic with exponential backoff 5. Monitor Rate Limits: Track Shopify API usage to avoid hitting limits Security Notes: - Requires valid API key authentication via X-API-Key header - Customer ID is validated against shop ownership - Cannot sync customers from other shops - All sync operations are logged for audit compliance Response: - Returns HTTP 204 No Content on successful sync - No response body returned - Check activity logs for detailed sync results Alternative Approaches: If you need to: - Sync multiple customers: Use bulk sync endpoint or scheduled job - Real-time updates: Rely on webhook subscriptions - Verify data without modifying: Use GET endpoints to retrieve current data Integration Workflow Example: 1. Customer contacts support about incorrect billing date 2. Support agent checks subscription in Appstle admin 3. Agent makes correction in Shopify admin 4. Agent calls sync endpoint for this customer 5. Sync retrieves latest data from Shopify 6. Appstle database is updated with corrected billing date 7. Customer portal now shows correct date 8. Support ticket resolved Authentication: Requires valid X-API-Key header or api_key parameter (deprecated) ## Get detailed subscription information for a customer - [GET /api/external/v2/subscription-customers-detail/valid/{customerId}](https://developers.subscription.appstle.com/external-api-swagger/customers/getvalidsubscriptioncustomerdetailsv2.md): Retrieves comprehensive subscription contract details for a specific customer, including subscription status, products, billing information, delivery schedules, and more. This endpoint returns full subscription objects with all associated data, making it ideal for displaying subscription management interfaces and detailed analytics. What This Endpoint Returns: Unlike the contract IDs endpoint which returns only numeric IDs, this endpoint provides complete SubscriptionContractDetailsDTO objects for each of the customer's subscriptions. Each object contains all information needed to display and manage a subscription. Data Included in Response: Subscription Identity: - Subscription contract ID (Shopify numeric ID) - Subscription GraphQL ID (Shopify GID format) - Internal Appstle database ID - Contract creation date Subscription Status & Lifecycle: - Current status (ACTIVE, PAUSED, CANCELLED, EXPIRED, FAILED) - Status reason (why paused/cancelled) - Next billing date and time - Contract anchor date - Cancellation date (if applicable) - Current billing cycle number - Min/max cycle limits Billing Configuration: - Billing interval (WEEK, MONTH, YEAR) - Billing interval count (e.g., every 2 weeks) - Billing policy (pricing details) - Currency code - Recurring total price - Applied discounts and pricing policies Delivery Configuration: - Delivery interval (WEEK, MONTH, YEAR) - Delivery interval count - Delivery method (SHIPPING, PICK_UP, LOCAL_DELIVERY) - Delivery policy details - Delivery price Products & Line Items: - All subscribed products and variants - Product titles, SKUs, and images - Quantities per product - Individual line item prices - Product-specific discounts - Line item attributes and custom fields Customer Information: - Customer ID and GraphQL ID - Customer name and email - Customer acceptance status Address Details: - Billing address (full address object) - Shipping address (full address object) - Address validation status Payment Information: - Payment instrument type - Payment method details (card last 4, etc.) - Payment gateway used Order & Fulfillment: - Last order ID and details - Last order date - Order note - Fulfillment status Additional Metadata: - Custom note attributes - Tags and labels - Internal flags and settings - Selling plan ID and group ID - Shop domain Use Cases: 1. Customer Portal: - Display all subscriptions on customer dashboard - Show subscription details page - Enable subscription management actions - Display upcoming order information 2. Admin Dashboard: - View customer's complete subscription portfolio - Analyze subscription health and status - Identify at-risk or high-value subscriptions - Generate customer subscription reports 3. Customer Support: - Quick access to all customer subscription details - Troubleshoot billing or delivery issues - Verify subscription configurations - Assist with subscription modifications 4. Analytics & Reporting: - Calculate customer lifetime value - Analyze subscription mix per customer - Track subscription frequency distribution - Identify cross-sell/upsell opportunities 5. Integration & Automation: - Sync subscription data to CRM/analytics platforms - Trigger workflows based on subscription details - Build custom reporting dashboards - Export subscription data for analysis Response Format: Returns an array of SubscriptionContractDetailsDTO objects: json [ { "id": 789, "subscriptionContractId": 5234567890, "status": "ACTIVE", "nextBillingDate": "2024-03-15T00:00:00Z", "billingInterval": "MONTH", "billingIntervalCount": 1, "deliveryInterval": "MONTH", "deliveryIntervalCount": 1, "currencyCode": "USD", "currentTotalPrice": "49.99", "customerId": 12345, "customerEmail": "customer@example.com", "lineItems": [...], "billingAddress": {...}, "shippingAddress": {...} }, {...} ] Response Scenarios: Customer with no subscriptions: json [] Returns empty array with 200 OK status (not an error). Customer with multiple subscriptions: Array contains multiple subscription objects, each representing a separate subscription contract. Performance Considerations: Response Size: - Each subscription object can be 5-50 KB depending on line items - Customer with 10 subscriptions: ~100-500 KB response - Consider pagination or filtering for customers with 20+ subscriptions Query Performance: - Typical response time: 200-500ms - Slower for customers with many subscriptions or complex products - Database query is optimized with indexed lookups Best Practices: 1. Cache Results: Cache response data to minimize API calls 2. Filter Client-Side: Filter/sort subscriptions on client after retrieval 3. Selective Display: Don't display all fields if not needed 4. Handle Empty Array: Always gracefully handle case with no subscriptions 5. Optimize Images: Product images can be large - lazy load if displaying Data Freshness: - Data is retrieved from Appstle database (not real-time Shopify query) - Updated via webhooks with < 1 second lag typically - Use sync endpoint if data appears stale Security Notes: - Customer ID is validated against authenticated shop - Returns only subscriptions belonging to specified customer - Cannot access customers from other shops - Sensitive payment details (full card numbers) are never returned Comparison with Other Endpoints: vs. GET /subscription-customers/valid/{customerId}: - This endpoint: Returns complete subscription details - Valid contracts endpoint: Returns only contract IDs - Use this when you need full subscription information vs. GET /subscription-contract-details: - This endpoint: Filtered by single customer - Contract details endpoint: Query across all customers with filters - Use this for customer-specific views vs. GET /subscription-contracts/contract-external/{contractId}: - This endpoint: All contracts for a customer - Contract external endpoint: Single contract with Shopify raw data - Use this for customer overview, other for detailed single contract Authentication: Requires valid X-API-Key header or api_key parameter (deprecated) ## Get customer payment methods from Shopify - [GET /api/external/v2/subscription-contract-details/shopify/customer/{customerId}/payment-methods](https://developers.subscription.appstle.com/external-api-swagger/customers/getshopifycustomerpaymentdetails.md): Retrieves all payment methods associated with a customer directly from Shopify's payment API. This endpoint returns detailed information about stored payment instruments including credit/debit cards, digital wallets, and other payment methods that the customer can use for subscription billing. What This Endpoint Does: Queries Shopify's GraphQL API to fetch the customer's payment methods, including active instruments and optionally revoked (expired, removed, or failed) payment methods. This provides real-time payment method data directly from Shopify's payment vault. Payment Method Types Supported: Credit/Debit Cards: - Visa, Mastercard, American Express, Discover - Card last 4 digits - Expiry month and year - Card brand and type - Billing address associated with card Digital Wallets: - Shop Pay - Apple Pay - Google Pay - PayPal (when stored) Alternative Payment Methods: - Bank accounts (ACH, SEPA) - Buy Now Pay Later instruments - Store credit Payment Method Information Returned: For Each Payment Method: - Payment Instrument ID: Unique identifier (used for updates) - Display Name: Human-readable name (e.g., "Visa ending in 4242") - Payment Type: Card, wallet, bank account, etc. - Status: ACTIVE, REVOKED, EXPIRED, FAILED - Is Default: Whether this is the customer's default payment method - Last 4 Digits: For cards and bank accounts - Expiry Date: For cards (month/year) - Brand: Visa, Mastercard, Amex, etc. - Billing Address: Address associated with payment method - Created Date: When payment method was added Query Parameters: allowRevokedMethod (optional, default: false): - false: Returns only active, usable payment methods - true: Returns both active AND revoked payment methods Revoked Payment Methods: Include expired cards, deleted payment methods, failed instruments, and customer-removed methods. Useful for historical records and troubleshooting, but cannot be used for new billing attempts. Use Cases: 1. Customer Portal: - Display saved payment methods - Allow customer to select default payment method - Show payment method update/delete options - Validate payment methods before subscription modification 2. Subscription Management: - Verify customer has valid payment method before creating subscription - Check payment method expiry before next billing - Identify subscriptions at risk due to expiring cards - Prompt customer to update payment if needed 3. Payment Method Updates: - List available payment methods for customer selection - Identify payment instrument ID for update operations - Validate payment method before switching subscription 4. Troubleshooting & Support: - Debug payment failures - Verify which payment method is being used - Check if payment method is expired or revoked - Assist customer with payment issues 5. Analytics & Alerts: - Track payment methods approaching expiry - Send proactive notifications to update cards - Analyze payment method distribution - Identify customers with no valid payment methods Response Structure: Returns CustomerPaymentMethodsQuery.PaymentMethods object from Shopify GraphQL: json { "nodes": [ { "id": "gid://shopify/CustomerPaymentMethod/abc123", "instrument": { "__typename": "CustomerCreditCard", "brand": "VISA", "lastDigits": "4242", "expiryMonth": 12, "expiryYear": 2025, "name": "John Doe" }, "revokedAt": null, "revokedReason": null, "subscriptionContracts": [...] } ] } Common Scenarios: Scenario 1: Customer with multiple cards Returns array with multiple payment method objects, each representing a stored card. Scenario 2: Customer with no payment methods Returns empty nodes array - customer needs to add payment method. Scenario 3: Expired card included (allowRevokedMethod=true) Returns both active cards and expired/revoked cards with revokedAt timestamp. Important Considerations: Data Source: - Queries Shopify API in real-time (not Appstle database) - Always returns current Shopify payment method state - Subject to Shopify API rate limits Performance: - Response time: 300-800ms (depends on Shopify API) - Slower than database queries - Consider caching for non-critical displays Security: - Never returns full card numbers (PCI compliance) - Returns only last 4 digits - CVV is never stored or returned - Payment instrument IDs are tokenized references Privacy: - Customer ID validated against shop - Cannot query payment methods from other shops - Requires appropriate API permissions Best Practices: 1. Default to Active Only: Use allowRevokedMethod=false for payment selection UIs 2. Check Expiry Dates: Validate card expiry before using for subscriptions 3. Cache Responsibly: Cache for short periods (5-10 min) to reduce API calls 4. Handle Empty Response: Always handle case where customer has no payment methods 5. Show User-Friendly Names: Display brand and last 4 (e.g., "Visa •••• 4242") 6. Indicate Default: Highlight the default payment method clearly Integration Examples: Example 1: Display payment methods in customer portal javascript const paymentMethods = await fetch( /api/external/v2/subscription-contract-details/shopify/customer/${customerId}/payment-methods, { headers: { 'X-API-Key': 'your-key' } } ).then(r => r.json()); paymentMethods.nodes.forEach(pm => { if (pm.instrument.__typename === 'CustomerCreditCard') { console.log(${pm.instrument.brand} ending in ${pm.instrument.lastDigits}); if (pm.instrument.expiryYear !pm.revokedAt && pm.instrument.expiryYear >= currentYear ); if (!hasValidPayment) { alert('Please add a valid payment method before subscribing'); } Related Endpoints: - PUT /api/external/v2/subscription-contracts-update-payment-method - Update subscription payment method - POST /api/external/v2/associate-shopify-customer-to-external-payment-gateways - Add external payment method Authentication: Requires valid X-API-Key header ## Retrieve customers with subscriptions - [GET /api/external/v2/subscription-contract-details/customers](https://developers.subscription.appstle.com/external-api-swagger/customers/getallsubscriptioncontractdetailsbyshop.md): Returns a paginated list of customers who have subscription contracts. Supports filtering by customer name, email, and subscription count. ## Generate customer portal access link by customer ID or email - [GET /api/external/v2/manage-subscription-link](https://developers.subscription.appstle.com/external-api-swagger/customers/getmanagesubscriptionlinkv3.md): 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 = Hi ${customerName}, Manage your subscription: Manage Subscription Link expires ${formatDate(response.tokenExpirationTime)} ; 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 ## Generate customer portal link - [GET /api/external/v2/manage-subscription-link/{customerId}](https://developers.subscription.appstle.com/external-api-swagger/customers/getmanagesubscriptionlink.md): Generates a secure, time-limited link that allows customers to access their subscription management portal. This link provides customers with self-service capabilities to manage their subscriptions without requiring login credentials. Key Features: - Generates unique encrypted token for customer authentication - Token expires after 2 hours for security - Direct access to subscription management without password - Uses store's custom domain when available - Supports white-label customer portals Token Security: - Token contains encrypted customer ID, shop, and timestamp - Cannot be reused after expiration - Unique token generated for each request - Cryptographically secure encryption Customer Portal Access: Once customers click the link, they can: - View all active subscriptions - Update payment methods - Change delivery addresses - Modify product quantities - Pause or cancel subscriptions - Update delivery schedules - Apply discount codes - View order history Use Cases: - Email campaigns with 'Manage Subscription' CTAs - Customer service providing quick access - Post-purchase email flows - Account management integrations - Reducing support ticket volume URL Structure: The generated URL follows this pattern: https://[store-domain]/[manage-subscription-path]?token=[encrypted-token] Important Notes: - Links are single-use and expire after 2 hours - New link must be generated after expiration - Customer ID must be valid and active - Store must have customer portal configured Authentication: Requires valid X-API-Key header