# External APIs 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. Version: 0.0.1 ## Servers ``` https://subscription-admin.appstle.com ``` ## Download OpenAPI description [External APIs](https://developers.subscription.appstle.com/_bundle/external-api-swagger.yaml) ## Subscription Management Core APIs for managing the complete subscription lifecycle including creation, updates, pausing, resuming, and cancellation of subscriptions. ### Update delivery price for a subscription contract - [PUT /api/external/v2/subscription-contracts-update-delivery-price](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/updatedeliveryprice.md): Updates the fixed delivery price for all future orders in a subscription contract. This allows manual override of calculated shipping rates with a custom delivery fee. Key Features: - Sets a fixed delivery price regardless of shipping calculations - Overrides any dynamic shipping rates from carriers - Applies to all future orders immediately - Can set to 0 for free delivery - Automatically handles invalid discount codes - Tracks price changes in activity log How Delivery Pricing Works: - Calculated Rates: Default behavior uses carrier rates and rules - Manual Override: This endpoint sets a fixed price - Precedence: Manual price overrides all calculations - Currency: Always in shop's base currency Common Use Cases: - Free Shipping Promotions: Set to 0.00 - Flat Rate Shipping: Fixed price regardless of location - VIP Customer Rates: Special shipping prices - Subscription Perks: Reduced delivery fees - Price Corrections: Fix shipping calculation errors - Regional Adjustments: Custom rates for specific areas Impact on Orders: - Next order uses new delivery price - All future recurring orders affected - Existing orders keep original pricing - Customer sees updated total immediately - No recalculation on address changes Price Validation: - Must be a valid decimal number - Can be 0 for free shipping - No maximum limit enforced - Negative values typically rejected by Shopify - Currency precision respected (e.g., 2 decimals for USD) Side Effects: - Invalid discount codes automatically removed - Activity log created with old/new prices - No customer email notification sent - Shipping tax recalculated if applicable - Total order value updated Reverting to Calculated Rates: To restore dynamic shipping calculations: 1. Use the sync shipping price endpoint 2. Or update delivery method 3. Manual price remains until explicitly changed Important Notes: - Price includes all delivery charges (shipping + handling) - Does not affect delivery method or speed - Consider customer communication for increases - May affect subscription profitability - Some payment methods may decline on total changes Authentication: Requires valid X-API-Key header ### Update subscription contract status - [PUT /api/external/v2/subscription-contracts-update-status](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/updatestatusv2.md): Updates the status of a subscription contract to ACTIVE, PAUSED, or CANCELLED. This endpoint manages the lifecycle of subscriptions with automatic state tracking and notifications. Status Transitions: - ACTIVE: Resumes a paused subscription, enabling future billing and deliveries - PAUSED: Temporarily suspends all billing and deliveries until manually resumed - CANCELLED: Permanently terminates the subscription (irreversible) Key Features: - Validates status transitions (prevents same-status updates) - Tracks status change timestamps for audit trails - Sends automated email notifications to customers - Creates detailed activity logs for each status change - Handles concurrent modifications with automatic retry - Adjusts next billing date when resuming subscriptions Permission Requirements (Customer Portal): When called from customer portal context: - PAUSED status requires 'pauseResumeSub' permission - ACTIVE status (resuming) requires 'resumeSub' permission - CANCELLED status requires 'cancelSub' permission - External API calls bypass these permission checks Status Change Side Effects: - Activating: Recalculates next billing date, marks activation timestamp - Pausing: Stops all scheduled orders, marks pause timestamp - Cancelling: Terminates subscription permanently, marks cancellation timestamp Error Recovery: The system automatically handles: - Invalid discount codes by removing them and retrying - Concurrent modifications by retrying the operation - This ensures reliable status updates in production environments Important Notes: - Status values are case-insensitive - Cancelled subscriptions cannot be reactivated - Paused subscriptions retain all settings and can be resumed - Email notifications are sent automatically unless internally suppressed Authentication: Requires valid X-API-Key header ### Update subscription delivery address and method - [PUT /api/external/v2/subscription-contracts-update-shipping-address](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/updateshippingaddressv2.md): Updates the shipping address or delivery method for a subscription contract. Supports standard shipping, local delivery, and pickup options with comprehensive address validation. Delivery Method Types: - SHIPPING: Standard shipping to customer address (default) - LOCAL: Local delivery within specified zip codes - PICK_UP: Customer pickup at designated location Key Features: - Zip code restrictions for customer portal access - Optional ShipperHQ address validation - Automatic phone number handling for local delivery - Email notifications to customers - Shipping price recalculation - Activity log tracking with old/new addresses Zip Code Validation (Customer Portal Only): When called from customer portal: - Standard shipping: Validates against 'allowToSpecificZipCode' setting - Local delivery: Validates against 'allowToSpecificZipCodeForLocalDelivery' setting - External API calls bypass zip code restrictions Address Validation: - If ShipperHQ is configured, addresses are validated for deliverability - Invalid addresses will return appropriate error messages - Helps prevent failed deliveries and shipping issues Special Handling: - Local delivery addresses missing phone numbers are auto-populated - Uses customer's phone if available, otherwise defaults to placeholder - Handles missing address components gracefully Post-Update Actions: - Sends 'SHIPPING_ADDRESS_UPDATED' email to customer - Creates activity log with address change details - Triggers asynchronous shipping price recalculation - May remove invalid discount codes automatically Important Notes: - Province codes should use ISO 3166-2 format (e.g., 'NY' for New York) - Country codes should use ISO 3166-1 alpha-2 format (e.g., 'US') - Phone numbers should include country code for international addresses - Pickup locations must be pre-configured in Shopify Authentication: Requires valid X-API-Key header ### Update order note for subscription - [PUT /api/external/v2/subscription-contracts-update-order-note/{contractId}](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/updateordernotev2.md): Updates the order note that will be added to all future orders generated by this subscription. Order notes help merchants track special instructions, customer preferences, or internal information about the subscription. Key Features: - Note is automatically added to all future recurring orders - Visible in both merchant portal and customer portal - Appears in Shopify order details for easy reference - Changes apply to future orders only (existing orders unchanged) Common Use Cases: - Customer preferences: "No nuts - severe allergy" - Delivery instructions: "Leave package at side door" - Gift messages: "Happy Birthday from Mom!" - Internal notes: "VIP customer - priority handling" - Processing instructions: "Include sample with each order" Important Notes: - Empty string clears the existing note - No character limit imposed by API (check Shopify limits) - HTML is not rendered - stored as plain text - Updates are logged in activity history - Note persists until explicitly changed Order Generation: When Appstle creates recurring orders: 1. Retrieves current order note from subscription 2. Adds note to new Shopify order 3. Note appears in order details immediately 4. Merchants can still edit individual order notes Authentication: Requires valid X-API-Key header ### Update minimum cycles for a subscription contract - [PUT /api/external/v2/subscription-contracts-update-min-cycles](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/updatemincyclesv2.md): Updates the minimum number of billing cycles (orders) that a customer must complete before they can cancel their subscription. This creates a commitment period that helps with customer retention and business predictability. What are Minimum Cycles? Minimum cycles represent a commitment period where: - Customers must complete a specified number of orders - Cancellation is blocked until the minimum is met - Often tied to special pricing or promotional offers - Counted from the subscription start date Key Features: - Updates commitment period for existing subscriptions - Can increase or decrease minimum cycles - Setting to null removes the minimum commitment - Preserves all other subscription settings - Automatically handles invalid discount codes - Updates future billing queue after change Common Use Cases: - Promotional Offers: '3-month minimum for 50% off' - Hardware Subsidies: '12-month commitment with free device' - Loyalty Programs: Reduce minimum after customer proves loyalty - Seasonal Campaigns: Temporary commitment requirements - Contract Adjustments: Customer service exceptions Impact on Customers: - Cannot cancel via portal until minimum cycles complete - Pause/resume typically still allowed (check settings) - Shows commitment status in customer portal - No automatic notification sent (consider sending separately) Cycle Counting: - Only successful billing attempts count toward minimum - Failed payments don't increment the cycle count - Skipped orders (if allowed) don't count - Current cycle = successful past orders + 1 Interaction with Max Cycles: - Min cycles must be less than or equal to max cycles - If max cycles exist, subscription auto-cancels after maximum - Common pattern: 3 min cycles, 12 max cycles Best Practices: - Clearly communicate commitment terms upfront - Consider grandfathering existing customers - Use reasonable minimums (typically 3-12 cycles) - Document reason for changes in activity logs - Send customer notification for transparency Important Notes: - Changes apply immediately to cancellation logic - Doesn't affect past or in-progress orders - Customer portal respects this setting automatically - Activity log tracks old and new values - Consider legal requirements in your jurisdiction Authentication: Requires valid X-API-Key header ### Update maximum cycles for a subscription contract - [PUT /api/external/v2/subscription-contracts-update-max-cycles](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/updatemaxcyclesv2.md): Updates the maximum number of billing cycles (orders) after which a subscription will automatically terminate. This creates a fixed-duration subscription that ends after a specific number of orders. What are Maximum Cycles? Maximum cycles define subscription duration limits where: - Subscription automatically cancels after the specified number of orders - No further orders are generated once maximum is reached - Useful for fixed-term offers, trials, or seasonal subscriptions - Customer is notified before final order (if configured) Key Features: - Cannot set below current cycle count (prevents immediate cancellation) - Setting to null creates an indefinite subscription - Automatically reschedules order queue based on new limit - Preserves all other subscription settings - Validates against current subscription progress Current Cycle Calculation: - Current cycle = Successful billing attempts + 1 - Failed payments don't count toward maximum - First order is cycle 1, second is cycle 2, etc. - System prevents setting max below current position Common Use Cases: - Trial Subscriptions: '3-box trial' that auto-ends - Seasonal Programs: '6-month summer subscription' - Limited Series: '12-issue magazine subscription' - Promotional Offers: 'First 5 boxes at special price' - Gift Subscriptions: Fixed duration gifts that don't renew What Happens at Maximum: When a subscription reaches its maximum cycles: 1. Final order is processed normally 2. Subscription status changes to CANCELLED 3. No future orders are scheduled 4. Customer receives cancellation notification 5. Cannot be reactivated (new subscription required) Interaction with Min Cycles: - Can have both min and max (e.g., 3 min, 12 max) - Min cycles enforces commitment period - Max cycles enforces termination - Common pattern: Commitment with defined end Queue Management: After updating max cycles: - System recalculates future order schedule - Removes orders beyond the new maximum - Adjusts upcoming order notifications - Updates subscription end date projections Important Notes: - Validation prevents accidental immediate cancellation - Changes apply to future billing cycles only - Activity log tracks old and new values - Consider customer communication for changes - Setting null removes any duration limit Authentication: Requires valid X-API-Key header ### Update subscription delivery method - [PUT /api/external/v2/subscription-contracts-update-delivery-method](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/updatedeliverymethod.md): Updates the delivery method for a subscription contract, supporting standard shipping, local delivery, and customer pickup options. The delivery method determines how future orders will be fulfilled. Delivery Method Types: The system automatically determines the type based on the subscription's current delivery address: - SHIPPING: Standard shipping to customer address (default) - LOCAL: Local delivery within merchant's delivery zones - PICK_UP: Customer pickup at designated location Two Ways to Update: 1. Manual Parameters: Provide title, code, and presentment title directly 2. Delivery Method ID: Provide a Shopify DeliveryMethodDefinition ID to auto-populate all fields Using Delivery Method ID: When providing a delivery-method-id: - System fetches the method from Shopify's delivery profiles - Automatically sets title, code, and presentment title - Applies associated delivery price if defined - ID can be numeric or full GraphQL ID format Delivery Type Requirements: - Standard Shipping: No additional requirements - Local Delivery: Phone number must exist in delivery address - Pickup: Pickup location must be configured in subscription Price Updates: - If using delivery-method-id with a fixed price, updates delivery price - Manual updates don't change the delivery price - Price changes affect all future orders Side Effects: - Creates activity log entry with method details - May remove invalid discount codes automatically - Updates apply to all future orders immediately - No customer notification sent Common Use Cases: - Switch from standard shipping to express shipping - Change pickup location for customer convenience - Update local delivery options based on availability - Apply seasonal delivery methods Important Notes: - Cannot change the delivery type (shipping/local/pickup) - only the method within that type - Delivery methods must be configured in Shopify's shipping settings - Changes don't affect orders already in fulfillment Authentication: Requires valid X-API-Key header ### Update delivery interval for a subscription contract - [PUT /api/external/v2/subscription-contracts-update-delivery-interval](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/updatedeliveryintervalv2.md): Updates the delivery interval for the specified subscription contract. This endpoint allows external API consumers to change the delivery interval count and type (of type SellingPlanInterval) used for scheduling deliveries. The service validates that the contract exists, that the new delivery interval differs from the current setting, and that it meets all business rules. Authentication is enforced via the X-API-Key header (the 'api_key' parameter is deprecated). ### Update custom attributes on a subscription contract - [POST /api/external/v2/update-custom-note-attributes](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/updateordernoteattributes.md): Updates or replaces custom key-value attributes on a subscription contract. These attributes are stored with the subscription and can be used to track custom data, preferences, or metadata that's important for your business processes. Custom Attributes Overview: Custom attributes are key-value pairs that allow you to store additional information on subscriptions. They are: - Visible in the Shopify admin and accessible via API - Included in order data when subscription orders are created - Preserved across subscription lifecycle events - Useful for integrations and custom workflows Update Modes: - Merge Mode (overwriteExistingAttributes=false): Adds new attributes and updates existing ones with matching keys. Other attributes remain unchanged. - Replace Mode (overwriteExistingAttributes=true): Completely replaces all existing attributes with the provided list. Common Use Cases: - Store gift messages or special instructions - Track referral sources or marketing campaigns - Add internal reference numbers or tracking codes - Store customer preferences or customization options - Integration data for third-party systems Important Notes: - Attribute keys should not conflict with Shopify's reserved attributes - Both keys and values are stored as strings - Changes are logged in the activity history - Invalid discount codes may be automatically removed during update Authentication: Requires valid X-API-Key header ### Split or duplicate an existing subscription contract - [POST /api/external/v2/subscription-contract-details/split-existing-contract](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/splitexistingcontract.md): Creates a new subscription contract by either splitting (moving) or duplicating selected line items from an existing contract. This endpoint allows you to divide a subscription into multiple contracts or create a copy with specific products. Split vs Duplicate Mode: - Split (isSplitContract=true): Moves the selected line items from the original contract to a new contract. The original contract will no longer contain these items. - Duplicate (isSplitContract=false): Creates a new contract with copies of the selected line items while keeping them in the original contract. Important Notes: - When splitting, at least one subscription product must remain in the original contract - The new contract inherits all settings from the original: customer, payment method, billing/delivery policies, shipping address, and custom attributes - Billing schedule is automatically generated for the new contract - One-time products and free products don't count towards the minimum product requirement Use Cases: - Split a subscription when customer wants different delivery schedules for different products - Create a gift subscription from an existing subscription - Separate products for different shipping addresses - Duplicate a subscription for testing or backup purposes Authentication: Requires valid X-API-Key header ### Replace product variants in a subscription contract - [POST /api/external/v2/subscription-contract-details/replace-variants-v3](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/replacevariantsv3.md): Replaces existing product variants with new ones in a subscription contract. This endpoint supports both regular subscription products and one-time products, allowing you to swap products, update quantities, and manage the product mix in a subscription. Key Features: - Bulk Replace: Replace multiple products at once by providing lists of old and new variants - Line-Specific Replace: Target a specific line item using oldLineId for precise replacement - Quantity Management: Set new quantities for replaced products - One-Time Products: Add or remove one-time purchase products independently - Discount Preservation: Configurable discount carry-forward logic Discount Carry Forward Options: - PRODUCT_THEN_EXISTING: First tries to apply the new product's selling plan discount, then falls back to existing discount - PRODUCT_PLAN: Always uses the new product's selling plan discount - EXISTING_PLAN: Maintains the existing product's discount structure Important Notes: - At least one regular subscription product must remain in the contract - One-time products and free products don't count towards the minimum product requirement - The system automatically handles pricing adjustments based on billing/delivery intervals - Shipping prices are automatically recalculated after changes Use Cases: - Product upgrades/downgrades (e.g., switching coffee blend or size) - Quantity adjustments during product swap - Adding limited-time or seasonal products as one-time purchases - Bulk product replacements for subscription migrations Authentication: Requires valid X-API-Key header ### Create a new subscription contract - [POST /api/external/v2/subscription-contract-details/create-subscription-contract](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/createsubscriptioncontractv2.md): Creates a new subscription contract for a customer with specified products, billing frequency, and delivery details. This endpoint allows you to programmatically create subscriptions with custom pricing, delivery schedules, and multiple line items. The subscription will be created in Shopify and synchronized with the Appstle system. Important Notes: - Customer must have at least one valid payment method - If paymentMethodId is not provided, the default payment method will be used - If delivery interval is not specified, it defaults to the billing interval - Custom pricing policies can be applied per line item - All monetary values are in the store's base currency unless currencyCode is specified - CustomAttributes and line item customAttributes use Shopify's AttributeInput format: {"key": "string", "value": "string"} Pricing Policy Types: - SELLING_PLAN_PRICING_POLICY: Uses the default pricing from the selling plan - CUSTOM_PRICING_POLICY: Allows custom discount cycles defined in pricingPolicy array - NO_PRICING_POLICY: Uses the base price without any discounts Authentication: Requires valid X-API-Key header ### Get raw Shopify GraphQL contract response - [GET /api/external/v2/subscription-contracts/contract-external/{contractId}](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/getsubscriptioncontractrawexternalv2.md): Retrieves the complete, unprocessed subscription contract data directly from Shopify's GraphQL API. This endpoint returns the full Shopify subscription contract object exactly as Shopify provides it, including all nested fields, relationships, and GraphQL metadata. What This Endpoint Returns: Unlike processed/transformed endpoints, this returns Shopify's raw SubscriptionContract GraphQL object with all available fields. This is the same data structure you would receive if querying Shopify's GraphQL API directly, making it ideal for: - Debugging Shopify data synchronization issues - Accessing fields not exposed in other endpoints - Understanding complete Shopify contract structure - Building custom integrations requiring full data - Comparing Shopify source data with processed data Data Included: Contract Core: - Full subscription contract object from Shopify - All GraphQL __typename fields preserved - Complete nested object structures - All available Shopify contract fields Customer Information: - Complete customer object with all fields - Default address details - Customer tags and metadata - Marketing preferences Line Items: - Full line item details with edges/nodes structure - Product and variant complete objects - Pricing policies with all cycle discounts - Line item custom attributes - Current and original prices Billing & Delivery: - Complete billing policy object - Full delivery policy details - Delivery method with all fields - Delivery price breakdown - Billing anchor details Payment Information: - Payment method details (if available) - Customer payment instrument - Payment gateway information Orders & History: - Origin order details - Last payment status - Historical billing attempts (in Appstle) Use Cases: 1. Debugging & Troubleshooting: - Investigate data sync discrepancies - Verify what Shopify actually stores - Debug webhook payload issues - Compare expected vs actual data 2. Advanced Integrations: - Access Shopify-specific fields not in standard APIs - Build custom analytics using raw data - Integrate with Shopify GraphQL directly - Extract fields for custom processing 3. Data Analysis: - Analyze complete contract structure - Extract all available metadata - Build comprehensive data exports - Perform deep data audits 4. Development & Testing: - Understand Shopify's data model - Test new feature development - Verify API responses - Documentation and examples Response Structure: Returns SubscriptionContractQuery.SubscriptionContract object: json { "id": "gid://shopify/SubscriptionContract/123456789", "status": "ACTIVE", "nextBillingDate": "2024-03-15T00:00:00Z", "customer": { "id": "gid://shopify/Customer/987654321", "email": "customer@example.com", "displayName": "John Doe", "__typename": "Customer" }, "lines": { "edges": [ { "node": { "id": "gid://shopify/SubscriptionLine/111111", "quantity": 2, "variantId": "gid://shopify/ProductVariant/222222", "title": "Monthly Coffee Box", "variantTitle": "Medium Roast", "currentPrice": { "amount": "29.99", "currencyCode": "USD" }, "pricingPolicy": {...}, "__typename": "SubscriptionLine" } } ] }, "billingPolicy": { "interval": "MONTH", "intervalCount": 1, "minCycles": 3, "maxCycles": 12 }, "deliveryPolicy": {...}, "deliveryMethod": {...}, "__typename": "SubscriptionContract" } Important Considerations: Data Source: - Queries Shopify GraphQL API in real-time - NOT cached in Appstle database - Always returns current Shopify state - Subject to Shopify API rate limits Performance: - Slower than database queries (500-1500ms typical) - Makes real-time call to Shopify - Response size can be large (10-50 KB) - Use sparingly to avoid rate limits GraphQL Structure: - Includes __typename fields throughout - Uses GraphQL ID format (gid://shopify/...) - Nested edges/nodes structure for lists - All fields as defined in Shopify's schema Best Practices: 1. Use for Debugging: Perfect for troubleshooting data issues 2. Avoid Polling: Don't call repeatedly - use cached/processed endpoints instead 3. Cache Response: Cache the response if using for display 4. Parse Carefully: Handle GraphQL structure (edges/nodes) 5. Monitor Rate Limits: Each call counts against Shopify API limits When to Use vs Other Endpoints: Use this endpoint when: - Need complete Shopify contract data - Debugging synchronization issues - Accessing Shopify-specific fields - Building Shopify GraphQL integrations Use /api/external/v2/subscription-contract-details when: - Need processed, filtered contract data - Want faster response times - Querying multiple contracts - Building customer-facing UIs Authentication: Requires valid X-API-Key header ### Get subscription fulfillment details for latest order - [GET /api/external/v2/subscription-contract-details/subscription-fulfillments/{contractId}](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/getsubscriptionfulfillmentsexternalv2.md): Retrieves fulfillment information for the most recent successful order associated with a subscription contract. This includes tracking details, shipment status, delivery estimates, and fulfillment line items from Shopify. What This Endpoint Returns: Complete fulfillment data for the subscription's last successfully billed order, queried in real-time from Shopify's GraphQL API. Shows customers when and how their subscription items will be (or were) delivered. Fulfillment Data Included: Shipment Tracking: - Tracking numbers and URLs - Carrier information (USPS, FedEx, UPS, etc.) - Tracking company details - Tracking status updates Delivery Status: - Fulfillment status (fulfilled, in_transit, out_for_delivery, delivered, etc.) - Estimated delivery date - Actual delivery timestamp (if delivered) - Delivery method (shipping, pickup, local delivery) Fulfillment Details: - Fulfilled line items (which products shipped) - Quantities fulfilled - Fulfillment service (manual, automated, 3PL) - Fulfillment created/updated dates - Multiple fulfillments (if order shipped in parts) Location Information: - Fulfillment location/warehouse - Origin address details - Fulfillment service name Order Determination Logic: Which Order is Retrieved: 1. Finds most recent SUCCESS billing attempt for contract 2. If found: Uses that order's Shopify order ID 3. If none: Falls back to subscription's origin order ID 4. Queries Shopify for that order's fulfillments Why This Matters: - Shows CURRENT/LATEST fulfillment status - Not historical fulfillments from months ago - Reflects what customer is waiting for NOW - Updates after each new billing cycle Use Cases: 1. Customer Portal "Where's My Order": - Display tracking information - Show estimated delivery date - Provide carrier tracking links - Update fulfillment status 2. Subscription Order Tracking: - Track recurring order deliveries - Monitor fulfillment progress - Identify delayed shipments - Provide proactive delivery updates 3. Customer Support: - Answer "where is my order" questions - Verify shipment details - Troubleshoot delivery issues - Provide accurate tracking info 4. Automated Notifications: - Send tracking emails automatically - Notify customers of shipments - Alert on delivery completion - Trigger review request flows 5. Subscription Management: - Show fulfillment in subscription history - Display delivery patterns - Track fulfillment reliability - Monitor shipping performance Response Structure: Returns Shopify Order object with fulfillments: json { "id": "gid://shopify/Order/123456789", "name": "#1001", "fulfillmentOrders": { "edges": [ { "node": { "id": "gid://shopify/FulfillmentOrder/111111", "status": "SUCCESS", "fulfillments": { "edges": [ { "node": { "trackingInfo": [ { "number": "1Z999AA10123456784", "url": "https://wwwapps.ups.com/tracking/...", "company": "UPS" } ], "status": "IN_TRANSIT", "estimatedDeliveryAt": "2024-03-20T00:00:00Z", "deliveredAt": null } } ] } } } ] } } Common Scenarios: Scenario: Order Fulfilled & Shipped json { "trackingInfo": [{"number": "9400...", "company": "USPS"}], "status": "IN_TRANSIT", "estimatedDeliveryAt": "2024-03-18T00:00:00Z" } Scenario: Order Delivered json { "status": "DELIVERED", "deliveredAt": "2024-03-15T14:23:00Z" } Scenario: Not Yet Fulfilled json { "fulfillmentOrders": { "edges": [ { "node": { "status": "OPEN", "fulfillments": {"edges": []} } } ] } } Scenario: No Order Yet (New Subscription) Returns null or empty response Important Considerations: Real-Time Shopify Query: - Makes live call to Shopify GraphQL API - NOT cached data - Response time: 500-1500ms - Subject to Shopify rate limits Data Freshness: - Returns current fulfillment status from Shopify - Tracking updates reflect Shopify's data - May lag behind carrier's actual status - Shopify updates tracking periodically Null Responses: - Returns null if no orders exist yet - Returns null if order ID not found - Handle gracefully in UI Multiple Fulfillments: - Order may have multiple fulfillments (split shipments) - Each fulfillment has own tracking - Iterate through all fulfillment nodes Integration Example: Customer Portal - Track Shipment: javascript const order = await fetch( /api/external/v2/subscription-contract-details/subscription-fulfillments/${contractId}, { headers: { 'X-API-Key': 'your-key' } } ).then(r => r.json()); if (!order) { return 'No shipment information available yet.'; } const fulfillments = order.fulfillmentOrders?.edges || []; fulfillments.forEach(fo => { fo.node.fulfillments?.edges?.forEach(f => { const tracking = f.node.trackingInfo?.[0]; if (tracking) { console.log(Track with ${tracking.company}: ${tracking.number}); console.log(URL: ${tracking.url}); } }); }); Best Practices: 1. Cache Response: Cache for 30-60 minutes to reduce Shopify API calls 2. Handle Nulls: Always check for null/empty responses 3. Parse GraphQL: Navigate edges/nodes structure carefully 4. Show All Tracking: Display all fulfillments if multiple shipments 5. Link to Carrier: Provide clickable tracking URLs Authentication: Requires valid X-API-Key header ### Get current billing cycle number for a subscription contract - [GET /api/external/v2/subscription-contract-details/current-cycle/{contractId}](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/getcurrentcycleofsubscriptioncontractv2.md): Retrieves the current billing cycle number for a specific subscription contract. The cycle number represents how many successful billing attempts have occurred for this subscription, starting from 1 for the initial order. What is a Billing Cycle? A billing cycle represents one completed billing period in a subscription's lifetime. Each successful billing attempt increments the cycle count. This number is crucial for: - Tracking subscription progress towards minimum/maximum cycle limits - Applying cycle-based pricing adjustments (discounts after N cycles) - Determining eligibility for cancellation (minimum cycles requirement) - Calculating customer lifetime value - Analyzing subscription retention metrics How Cycle Counting Works: Initial Order: - Cycle 1 starts when subscription is first created - Initial order counts as the first billing cycle - Includes origin order that created the subscription Subsequent Orders: - Each successful billing attempt increments cycle by 1 - Only SUCCESS status billing attempts are counted - Failed/skipped billing attempts do NOT increment cycle - Paused subscriptions maintain their current cycle number Calculation Formula: Current Cycle = 1 + (Number of Successful Billing Attempts) Example Timeline: - Day 1: Subscription created, initial order → Cycle 1 - Day 30: First recurring order successful → Cycle 2 - Day 60: Second recurring order successful → Cycle 3 - Day 90: Billing fails (payment declined) → Still Cycle 3 - Day 95: Retry successful → Cycle 4 Use Cases: 1. Cancellation Eligibility: - Verify customer has met minimum cycle requirement - Enforce contract terms (e.g., "3 month minimum") - Display "Can cancel after N more orders" messaging - Block premature cancellations 2. Pricing Adjustments: - Apply introductory pricing for first N cycles - Trigger loyalty discounts after X cycles - Calculate when pricing changes take effect - Implement "First 3 months 50% off" promotions 3. Customer Retention: - Identify subscriptions at risky cycle counts - Send retention campaigns at specific milestones - Track average cycles before churn - Celebrate subscription anniversaries 4. Analytics & Reporting: - Calculate customer lifetime value (cycle × price) - Analyze subscription duration distribution - Track retention curves by cohort - Measure success of lifecycle campaigns 5. Customer Portal Display: - Show "Order #X of Y" progress indicators - Display remaining cycles until cancellation allowed - Show subscription tenure/loyalty status - Calculate and display subscription value earned Response Format: Returns a single integer representing the current cycle number: json 3 Response Examples: New subscription (just created): json 1 After 5 successful billing attempts: json 6 Note: Initial order (1) + 5 successful renewals = Cycle 6 Important Considerations: Cycle vs. Billing Attempts: - Failed billing attempts don't increment cycle - Skipped orders don't increment cycle - Manual order creation may not increment cycle - Cycle represents successful billing events only Paused Subscriptions: - Cycle number remains frozen while paused - Resumes at same cycle when un-paused - Pause duration doesn't affect cycle count Minimum/Maximum Cycles: - minCycles: Minimum cycles before cancellation allowed - maxCycles: Subscription auto-expires after this many cycles - Use this endpoint to check progress towards these limits Data Source: - Queries Appstle database (not Shopify API) - Counts records in subscription_billing_attempt table - Filters by SUCCESS status only - Fast response time ( r.json()); const minCycles = contract.minCycles || 0; if (currentCycle >= minCycles) { console.log('Customer can cancel now'); showCancelButton(); } else { const cyclesRemaining = minCycles - currentCycle; console.log(Must complete ${cyclesRemaining} more orders before canceling); showMinimumCommitmentMessage(cyclesRemaining); } Display progress to max cycles: javascript const currentCycle = await getCycleNumber(contractId); const maxCycles = contract.maxCycles; if (maxCycles) { const progress = (currentCycle / maxCycles) * 100; console.log(Subscription ${progress.toFixed(0)}% complete (${currentCycle}/${maxCycles})); if (currentCycle === maxCycles) { console.log('This is the final cycle - subscription will expire after this order'); } } `` Performance Characteristics: Fast Query: - Simple database count query - Indexed by shop and contractId - Typical response time: 50-150ms - Suitable for real-time UI updates Best Practices: 1. Cache Results: Cache cycle number briefly (few minutes) to reduce API calls 2. Combine with Contract Data: Fetch contract details simultaneously for min/max cycles 3. Handle Edge Cases: Account for subscriptions with no successful billings yet 4. Display Progress: Show cycle number in customer-friendly format ("Order 3 of 12") 5. Sync with Billing: Update cycle number after each billing attempt completes Common Misunderstandings: Myth: Cycle = Months Subscribed - Reality: Cycle = Successful billing attempts, not time elapsed - A paused subscription stays at same cycle for months - Failed payments don't advance the cycle Myth: First order is Cycle 0 - Reality: Cycles start at 1, not 0 - Initial/origin order is Cycle 1 Related Fields: - minCycles: Minimum cycles before cancellation (from contract) - maxCycles: Maximum cycles before auto-expiry (from contract) - billingInterval`: Frequency between cycles (from contract) Authentication: Requires valid X-API-Key header ### Get available billing intervals for selling plan(s) - [GET /api/external/v2/subscription-contract-details/billing-interval](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/getsubscriptioncontractbillinginterval.md): Retrieves all available billing frequency options configured for specific Shopify selling plan(s). Returns the complete set of billing intervals that customers can choose from, including frequency, interval type, and any associated discounts or pricing policies. What This Endpoint Does: Queries the subscription group plans database to find all frequency configurations associated with given selling plan ID(s). This is essential for building subscription frequency selectors in customer portals or during subscription modifications. Key Concepts: Selling Plans: - Shopify's mechanism for defining subscription options - Each product variant can have multiple selling plans - Selling plans define billing/delivery frequency - Plans are grouped in subscription groups Frequency Info: - Specific billing interval configuration - E.g., "Every 2 weeks", "Every month", "Every 3 months" - Includes pricing policies and discounts - Customers select from available frequencies Request Parameters: sellingPlanIds (required): - Comma-separated list of Shopify selling plan IDs - Example: "123456,123457,123458" - Can query single or multiple plans - Returns frequencies for ALL provided plans Lookup Process: 1. Parse selling plan IDs from comma-separated string 2. Find subscription groups containing these plans 3. Extract frequency configurations from group JSON 4. Return all matching frequency options 5. Deduplicate if same frequency appears multiple times Response Data Included: For Each Frequency Option: - id: Selling plan ID - frequencyName: Display name (e.g., "Monthly") - interval: WEEK, MONTH, or YEAR - intervalCount: Number of intervals (e.g., 2 for bi-weekly) - deliveryInterval: Same or different from billing - deliveryIntervalCount: Delivery frequency - pricingPolicy: Discount configuration - billingPolicy: Min/max cycles, anchor settings Pricing Policy Details: - Discount type (percentage, fixed amount) - Discount value - After cycle discounts (e.g., "50% off first 3 months") - Adjustment type Use Cases: 1. Frequency Selection UI: - Build dropdown/radio list of frequency options - Show available intervals to customers - Display pricing for each frequency - Enable subscription frequency changes 2. Subscription Modification: - Show current frequency and alternatives - Allow customers to switch frequencies - Validate new frequency selection - Preview pricing changes 3. Product Page: - Display subscription frequency options - Show "Subscribe and save" pricing - Calculate savings per frequency - Build subscription purchase selectors 4. Customer Portal: - "Change Frequency" functionality - Show all available options - Highlight current selection - Display pricing differences Response Format: json [ { "id": "123456", "frequencyName": "Every 2 Weeks", "interval": "WEEK", "intervalCount": 2, "deliveryInterval": "WEEK", "deliveryIntervalCount": 2, "pricingPolicy": { "adjustmentType": "PERCENTAGE", "adjustmentValue": "10.0" } }, { "id": "123457", "frequencyName": "Monthly", "interval": "MONTH", "intervalCount": 1, "deliveryInterval": "MONTH", "deliveryIntervalCount": 1, "pricingPolicy": { "adjustmentType": "PERCENTAGE", "adjustmentValue": "15.0" } } ] Integration Example: Customer Portal - Frequency Selector: javascript // Get selling plan from current subscription const currentSellingPlanId = subscription.sellingPlanId; // Fetch available frequencies const frequencies = await fetch( /api/external/v2/subscription-contract-details/billing-interval?sellingPlanIds=${currentSellingPlanId}, { headers: { 'X-API-Key': 'your-key' } } ).then(r => r.json()); // Build selector const selector = frequencies.map(freq => ${freq.frequencyName} - Save ${freq.pricingPolicy.adjustmentValue}% ).join(''); document.querySelector('#frequency-select').innerHTML = selector; Important Considerations: Data Source: - Queries Appstle database (NOT Shopify API) - Based on subscription group configuration - Fast response (< 100ms typically) - Data synced when groups are updated Multiple Selling Plans: - Can query multiple plans at once - Returns union of all frequencies - Useful for products with multiple subscription options - Results may contain duplicates if plans share frequencies Empty Results: - Returns empty array [] if no plans found - Returns empty if selling plan ID invalid - Not an error - handle gracefully Best Practices: 1. Query Relevant Plans: Only query selling plans for current product/variant 2. Display Discounts: Show savings clearly in UI 3. Sort by Interval: Order options logically (weekly → monthly → yearly) 4. Highlight Current: Clearly mark customer's current frequency 5. Cache Results: Cache frequency data per selling plan Authentication: Requires valid X-API-Key header ### Get subscription contract analytics and revenue metrics - [GET /api/external/v2/subscription-contract-details/analytics/{contractId}](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/getsubscriptioncontractanalyticsbycontractidexternalv2.md): Retrieves comprehensive analytics for a specific subscription contract, including total revenue generated, number of successful orders, and formatted revenue display. This endpoint provides key performance metrics for understanding the financial impact of individual subscriptions. What This Endpoint Returns: Financial and operational analytics for a single subscription contract, calculated from all successful billing attempts throughout the subscription's lifetime. Unlike realtime contract queries, this provides historical aggregated data. Metrics Included: Revenue Metrics: - totalOrderAmount: Total revenue in decimal format (e.g., 299.95) - totalOrderRevenue: Formatted currency string (e.g., "$299.95") - Calculated from all SUCCESS status billing attempts - Includes taxes, shipping, and discounts - Does NOT include failed or pending payments Order Count: - totalOrders: Count of successful billing attempts - Represents number of orders generated by subscription - Does NOT include failed billing attempts - Starts at 0 for brand new subscriptions Currency Formatting: - Uses shop's configured money_format - Respects shop's currency code (USD, EUR, GBP, etc.) - Handles currency symbols and decimal places correctly - Falls back to USD if currency unknown Calculation Logic: Data Source: sql SELECT COUNT(*) as totalOrders, SUM(order_amount) as totalOrderAmount FROM subscription_billing_attempt WHERE shop = ? AND contract_id = ? AND status = 'SUCCESS' What Gets Counted: - ✅ Initial subscription order - ✅ All successful recurring orders - ✅ Manual billing attempts that succeeded - ✅ Retry attempts that eventually succeeded - ❌ Failed payment attempts - ❌ Skipped billing cycles - ❌ Cancelled/voided orders - ❌ Pending/in-progress billing Use Cases: 1. Customer Lifetime Value: - Calculate total revenue from specific customer - Measure subscription ROI - Identify high-value subscriptions - Track revenue growth over time 2. Subscription Performance: - Analyze revenue per subscription - Compare subscriptions by total value - Identify most profitable subscription types - Calculate average order value 3. Customer Portal: - Display "You've saved $XXX" messaging - Show "X orders delivered" stats - Celebrate subscription milestones - Build customer loyalty through transparency 4. Reporting & Analytics: - Build subscription revenue dashboards - Generate customer value reports - Track subscription health metrics - Forecast future revenue 5. Business Intelligence: - Segment customers by subscription value - Identify churn risk (low order count) - Calculate retention rates - Measure subscription program success Response Format: json { "totalOrders": 12, "totalOrderAmount": 599.88, "totalOrderRevenue": "$599.88" } Response Fields: - totalOrders (integer): Count of successful billing attempts - totalOrderAmount (decimal): Numeric revenue total - totalOrderRevenue (string): Formatted currency display Example Scenarios: Brand New Subscription: json { "totalOrders": 0, "totalOrderAmount": 0.00, "totalOrderRevenue": "$0.00" } After First Successful Order: json { "totalOrders": 1, "totalOrderAmount": 49.99, "totalOrderRevenue": "$49.99" } Established Subscription (EUR): json { "totalOrders": 24, "totalOrderAmount": 1199.76, "totalOrderRevenue": "€1.199,76" } Integration Examples: Customer Portal - Loyalty Display: javascript const analytics = await fetch( /api/external/v2/subscription-contract-details/analytics/${contractId}, { headers: { 'X-API-Key': 'your-key' } } ).then(r => r.json()); const loyaltyMessage = Thank you for your loyalty! You've received ${analytics.totalOrders} orders Total value: ${analytics.totalOrderRevenue} ; Revenue Dashboard: javascript // Fetch analytics for multiple subscriptions const contractIds = [123, 456, 789]; const analyticsPromises = contractIds.map(id => getContractAnalytics(id) ); const allAnalytics = await Promise.all(analyticsPromises); const totalRevenue = allAnalytics.reduce( (sum, a) => sum + a.totalOrderAmount, 0 ); console.log(Total subscription revenue: $${totalRevenue.toFixed(2)}); Important Considerations: Data Accuracy: - Based on Appstle's billing attempt records - May differ slightly from Shopify order totals - Includes only what Appstle successfully billed - Updated after each billing attempt completes Currency Handling: - Formatting uses shop's money_format setting - Different shops may have different decimal separators - Currency symbol placement varies by locale - Always use totalOrderAmount for calculations Performance: - Fast database aggregation query - Typical response time: 100-300ms - Indexed by shop and contract ID - Suitable for real-time display Best Practices: 1. Use for Display: Use totalOrderRevenue for customer-facing display 2. Calculate with Amount: Use totalOrderAmount for mathematical operations 3. Cache Strategically: Cache for dashboards, fetch real-time for critical displays 4. Handle Zero: Gracefully handle new subscriptions with 0 orders 5. Validate Contract: Ensure contract exists before querying analytics Limitations: What's NOT Included: - Future projected revenue - Failed payment attempt counts - Refunds or chargebacks - Pending/processing orders - Orders from other subscriptions Related Calculations: Average Order Value: javascript const aov = analytics.totalOrderAmount / analytics.totalOrders; console.log(Average order value: $${aov.toFixed(2)}); Customer Lifetime Value (projected): javascript const monthsActive = calculateMonthsActive(contract.createdAt); const monthlyRevenue = analytics.totalOrderAmount / monthsActive; const projectedLTV = monthlyRevenue * 12; // Annual LTV Authentication: Requires valid X-API-Key header ### Get delivery options for subscription contract - [GET /api/external/v2/data/contract-delivery-options](https://developers.subscription.appstle.com/external-api-swagger/subscription-management/getcontractdeliveryoptions.md): Retrieves all valid delivery methods available for a specific subscription contract. Returns shipping profiles and delivery options based on the contract's delivery address and product characteristics. Delivery Information Returned: - Available shipping profiles - Delivery methods for each profile - Shipping rates and costs - Delivery speed (standard, express, etc.) - Method names and descriptions - Eligibility based on address and products Filtering Behavior: By default, returns only delivery methods valid for the contract: - Matches delivery address country/region - Compatible with subscription products - Available for contract weight/dimensions Include All Methods: Use header X-Include-All-Methods: true to return all delivery methods regardless of eligibility. Useful for admin UIs where you want to show all options. Use Cases: - Display delivery method selector in customer portal - Allow customers to change shipping method - Calculate shipping costs for subscription - Validate delivery method during subscription updates - Show upgrade options (standard to express) Common Scenarios: Customer Portal - Change Delivery Speed: 1. Call this endpoint with contractId 2. Display available methods to customer 3. Customer selects preferred method 4. Update subscription with new delivery method ID Subscription Creation - Delivery Selection: 1. Get delivery options for draft contract 2. Present options during checkout/signup 3. Create subscription with selected method Important Notes: - Delivery options depend on current contract address - Changing address may change available methods - Costs may vary based on products in subscription - Some methods may have minimum order requirements - International shipping may have additional restrictions Authentication: Requires X-API-Key header ## Subscription Payments APIs for managing subscription payment methods, processing payments, handling payment retries, and updating billing information. ### Send payment method update email to customer - [PUT /api/external/v2/subscription-contracts-update-payment-method](https://developers.subscription.appstle.com/external-api-swagger/subscription-payments/updatepaymentmethodv2.md): Triggers Shopify to send an email to the subscription customer with a secure link to update their payment method. This endpoint initiates Shopify's native payment update flow without requiring direct payment handling. Key Features: - Sends official Shopify payment update email to customer - Customer receives secure link to Shopify-hosted payment update page - No PCI compliance required - Shopify handles all payment data - Supports all Shopify-supported payment methods - Automatically updates subscription after customer completes the process Process Flow: 1. API call triggers email send request to Shopify 2. Shopify sends branded email to customer's registered email 3. Customer clicks secure link in email 4. Customer authenticates on Shopify-hosted page 5. Customer adds/updates payment method 6. Subscription automatically uses new payment method Email Details: - Sent from Shopify's email servers - Uses store's configured sender email - Subject line typically: "Update your payment method" - Contains secure, time-limited link - Shopify-branded with store information Use Cases: - Failed payment recovery - Expiring credit card updates - Customer-requested payment changes - Proactive payment method maintenance Important Notes: - Customer must have valid email address - Email cannot be customized (Shopify template) - Link expiration time set by Shopify - Multiple emails can be sent if needed - No webhook for completion - poll contract for updates Rate Limiting: - Subject to Shopify's email sending limits - Recommended: Wait 24 hours between sends to same customer - Excessive sends may be blocked by Shopify Authentication: Requires valid X-API-Key header ### Update subscription payment method - [PUT /api/external/v2/subscription-contracts-update-existing-payment-method](https://developers.subscription.appstle.com/external-api-swagger/subscription-payments/updateexistingpaymentmethodv2.md): Updates the payment method for an existing subscription contract to use a different existing payment method. The new payment method must already be associated with the customer in Shopify. Important Notes: - The payment method must already exist in the customer's Shopify payment methods - Only valid, non-revoked payment methods can be used - The update is processed through Shopify's subscription draft system - Payment method details are cached locally after successful update Process Flow: 1. Validates subscription contract exists 2. Creates a draft update in Shopify 3. Updates the draft with new payment method 4. Commits the draft to apply changes 5. Caches payment instrument details locally 6. Records activity log entry Authentication: Requires valid X-API-Key header ## Subscription Contracts APIs for managing subscription contracts including delivery schedules, pricing, order notes, billing cycles, and shipping addresses. ### Update multiple line item attributes for a subscription contract - [PUT /api/external/v2/subscription-contracts-update-multiple-line-item-attributes](https://developers.subscription.appstle.com/external-api-swagger/subscription-contracts/updatemultiplelineitemattributesv2.md): Updates custom attributes for multiple line items within a subscription contract. The request body must be a JSON object where each key is a line item identifier (as a String) and each value is a list of AttributeInfo objects containing attribute key/value pairs. For example: { "gid://shopify/SubscriptionLineItem/987654321": [ { "key": "color", "value": "red" }, { "key": "size", "value": "M" } ] }. The service validates that the contract exists and that each specified line item is eligible for update. Authentication is performed via the X-API-Key header (the 'api_key' parameter is deprecated). ### Update line item attributes for a subscription contract - [PUT /api/external/v2/subscription-contracts-update-line-item-attributes](https://developers.subscription.appstle.com/external-api-swagger/subscription-contracts/updatelineitemattributesv2.md): Updates the custom attributes for a specific line item within a subscription contract. This endpoint accepts a contract ID, a line item ID, and a list of attribute objects (each containing key/value pairs) to update. It uses the underlying service to perform validation (such as contract existence, freeze status, and attribute-based cycle limits) before applying the update. The operation is intended for external API consumers, and authentication is performed via the X-API-Key header. Deprecated api_key parameter is supported for backward compatibility. ### Update Subscription contract frequency by selling plan - [PUT /api/external/v2/subscription-contracts-update-frequency-by-selling-plan](https://developers.subscription.appstle.com/external-api-swagger/subscription-contracts/updatefrequencybysellingplanv2.md) ### Replace all line item attributes in bulk across subscription contracts - [PUT /api/external/v2/subscription-contracts-bulk-update-line-item-attributes](https://developers.subscription.appstle.com/external-api-swagger/subscription-contracts/updatemultiplecontractslineitemattributesv2.md): This API replaces all existing attributes for the specified line items within subscription contracts. Use carefully, as any attributes not included in the request will be removed. ### Retrieve subscription contracts - [GET /api/external/v2/subscription-contract-details](https://developers.subscription.appstle.com/external-api-swagger/subscription-contracts/getallsubscriptioncontractdetails.md): Retrieves a paginated list of subscription contracts with powerful filtering capabilities. This endpoint enables complex queries to find specific subscriptions based on various criteria including dates, customer information, product details, and subscription characteristics. Key Features: - Comprehensive filtering across 20+ parameters - Full pagination support with customizable page size - Partial text matching for customer and order searches - Date range filtering for multiple date fields - Product and variant filtering within line items - Order amount range filtering - Plan type differentiation (prepaid vs pay-per-delivery) Pagination: - Uses Spring's Pageable format - Default page size: 20 items - Maximum page size: 2000 items (exceeding this limit will result in a 400 error) - Returns total count in X-Total-Count header - Provides navigation links in Link header IMPORTANT - Sorting Limitations: Due to the use of native SQL queries, sort parameters MUST use database column names (snake_case) rather than Java field names (camelCase). Common sorting examples: - sort=next_billing_date,asc (NOT nextBillingDate) - sort=customer_name,desc (NOT customerName) - sort=created_at,asc (NOT createdAt) - sort=subscription_contract_id,desc (NOT subscriptionContractId) - sort=order_amount,asc (NOT orderAmount) Date Format: All date parameters use ISO 8601 format with timezone: yyyy-MM-dd'T'HH:mm:ssXXX Examples: 2024-03-15T10:30:00+00:00 or 2024-03-15T10:30:00Z Date Range Filtering: - For created, updated dates: Can use either 'from', 'to', or both - For next billing date: Both 'from' and 'to' must be provided together (current limitation) Text Search Behavior: - Customer name searches both name and email fields - Order name searches current and historical orders (in subscription_billing_attempt table) - All text searches are case-insensitive - Partial matches are supported (contains logic) - Subscription contract ID search supports partial numeric matching Plan Type Classification: - prepaid: Billing interval > delivery interval - non-prepaid: Billing interval = delivery interval Performance Considerations: - Complex filters (especially JSON searches and order amount calculations) may impact response time - Use specific filters when possible - Consider smaller page sizes for complex queries - Product, variant, and selling plan searches use JSON_SEARCH which may be slow on large datasets Authentication: Requires valid X-API-Key header (the deprecated 'api_key' query parameter is still accepted but not recommended) ### Retrieve raw Shopify GraphQL response for a subscription contract - [GET /api/external/v2/contract-raw-response](https://developers.subscription.appstle.com/external-api-swagger/subscription-contracts/getcontractrawresponse.md): Fetches the complete, unprocessed JSON response directly from Shopify's GraphQL API for the specified subscription contract. This endpoint returns the full subscription data structure as provided by Shopify, including all nested objects and relationships. Use Cases: - Debugging subscription issues - Accessing all available subscription data - Understanding the complete data structure - Building custom integrations Response Structure: The response includes complete details about: - Customer information (email, name, ID) - Line items (products, quantities, pricing) - Billing and delivery policies - Payment method details - Discounts and pricing policies - Order history and billing attempts - Custom attributes and notes Note: This is a direct Shopify response with GraphQL type information (__typename fields) Authentication: Requires valid X-API-Key header ### Cancel a subscription contract - [DELETE /api/external/v2/subscription-contracts/{id}](https://developers.subscription.appstle.com/external-api-swagger/subscription-contracts/deletesubscriptioncontractv2.md): Cancels an existing subscription contract. This operation terminates all future billing and delivery cycles for the subscription. The cancellation takes effect immediately. Important Notes: - Any pending/scheduled orders will be cancelled - The customer will receive a cancellation confirmation email if SUBSCRIPTION_CANCELLED email template is enabled - Cancellation feedback and notes are stored for analytics and reporting - Minimum cycle requirements ARE enforced via API (unlike internal cancellations) - If the subscription is under a free trial period, minimum cycles are not enforced Validation Rules: - Contract must exist and belong to the authenticated shop - Contract must not already be cancelled - Must have completed minimum required billing cycles (unless in trial) Post-Cancellation: - Status changes to 'cancelled' (lowercase) - Any pause settings are cleared - Cancellation feedback and notes are saved - Activity log entry is created - Cancellation email is sent (if enabled) - Any invalid discount codes are automatically removed Authentication: Requires valid X-API-Key header ## Subscription Products APIs for managing products within subscriptions including adding, removing, updating quantities, and swapping products. ### Update multiple properties of a subscription line item - [PUT /api/external/v2/subscription-contracts-update-line-item](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/updatelineitemv2.md): Comprehensive endpoint for updating a subscription line item's quantity, price, product variant, and/or selling plan in a single API call. Changes are applied intelligently - only modified values trigger updates. Key Features: - Update any combination of: quantity, price, variant, or selling plan - Intelligent change detection - only updates what's different - Automatic handling of prepaid subscription pricing - Preserves existing discount cycles when updating price - Partial success allowed - some updates may fail while others succeed - Each change creates separate activity log entries Prepaid Subscription Handling: For prepaid subscriptions (billing interval > delivery interval): - When isPricePerUnit=true: Price is multiplied by interval ratio - Example: Monthly billing, weekly delivery = price × 4 - When isPricePerUnit=false: Price is used as total billing amount Update Process: 1. Validates line item exists in the subscription 2. Calculates interval multiplier for prepaid logic 3. Updates in order: selling plan → price → quantity → variant 4. Each update uses separate Shopify GraphQL mutation 5. Failures are logged but don't block other updates Selling Plan Updates: - Can update by ID or name (name takes precedence) - Only updates if different from current plan - Useful for changing delivery frequency options Price Updates: - Preserves existing discount cycles (up to 2 cycles) - Recalculates cycle discounts based on new base price - Triggers shipping price recalculation - Sends price update email to customer Quantity Updates: - Validates against min/max quantity rules - Updates Build-a-Box totals if applicable - May trigger discount recalculations Variant Updates: - Changes the product itself (different SKU) - Validates new variant exists and is available - May affect pricing and discounts Important Notes: - All parameters except contractId and lineId are optional - Provide only the values you want to change - Price is always in shop's base currency - Changes apply to future orders only Authentication: Requires valid X-API-Key header ### Update selling plan for a subscription line item - [PUT /api/external/v2/subscription-contracts-update-line-item-selling-plan](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/updatelineitemsellingplan.md): Updates the selling plan associated with a specific product line item in a subscription contract. Selling plans define the delivery schedule, pricing rules, and billing policies for subscription products. What are Selling Plans? Selling plans are Shopify's way of defining subscription rules for products: - Delivery Schedule: How often the product is delivered (e.g., 'every 2 weeks', 'monthly') - Pricing Policy: Discounts and pricing tiers (e.g., '10% off', 'first order free') - Billing Policy: When and how often customer is charged - Plan Name: Customer-facing description like 'Deliver every month' Key Features: - Update by selling plan ID or name (name takes precedence if both provided) - Validates line item exists before attempting update - Only creates activity log if plan actually changes - Uses Shopify's draft system for safe updates - Preserves existing line item attributes and customizations Common Use Cases: - Change delivery frequency: Weekly → Monthly - Switch pricing tiers: Regular → VIP pricing - Update from old plan to new plan with better terms - Migrate products to new selling plan groups - Apply seasonal or promotional plans Update Process: 1. Validates subscription contract and line item exist 2. Creates a draft of the subscription contract 3. Updates the line item's selling plan in the draft 4. Commits the draft to apply changes 5. Records activity log if plan changed Impact of Selling Plan Changes: - Delivery Schedule: Next and future orders follow new schedule - Pricing: New plan's pricing applies from next billing - Discounts: Plan-specific discounts are recalculated - Billing: Billing frequency may change with the plan Finding Selling Plans: To find available selling plans: 1. Check product's selling plan groups in Shopify admin 2. Use Shopify's GraphQL API to query selling plans 3. Plans must be active and associated with the product Important Notes: - Both sellingPlanId and sellingPlanName are optional, but at least one required - If both provided, both are updated (name doesn't override ID) - Plan must be valid for the product variant - Changes apply to future orders only - No customer notification sent (consider sending separately) Authentication: Requires valid X-API-Key header ### Update product line item quantity in subscription - [PUT /api/external/v2/subscription-contracts-update-line-item-quantity](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/updatelineitemquantityv2.md): Updates the quantity of a specific product line item within a subscription contract. This comprehensive operation handles quantity validation, discount recalculation, and special Build-a-Box constraints. Key Features: - Updates quantity for future orders only - Validates minimum/maximum quantities for line items - Special handling for Build-a-Box subscriptions - Automatic discount recalculation - Shipping price updates - Activity log tracking with old/new values Build-a-Box (BAB) Validation: For Build-a-Box subscriptions: - Enforces total minimum/maximum item counts - Only counts recurring products (excludes one-time and free items) - Validates across all BAB items in the subscription - Can be bypassed with 'allowToAddProductQuantityMinMaxReached' permission Line Item Validation: Individual products may have: - Minimum quantity requirements (min_quantity attribute) - Maximum quantity limits (max_quantity attribute) - These are enforced separately from BAB constraints Post-Update Actions: 1. Activity Logging: Records quantity change with old/new values 2. BAB Discount Sync: Recalculates Build-a-Box volume discounts 3. Product Discount Sync: Updates product-specific discounts 4. Shipping Price Update: Recalculates shipping based on new quantity Discount Recalculation: - Build-a-Box discounts adjust based on total quantity tiers - May remove old discount codes and apply new ones - Handles 'subscription contract has changed' retry scenarios Important Notes: - Line ID must be the full GraphQL ID format - Quantity must be positive (minimum 1) - Changes apply to all future orders - Past or in-progress orders are not affected Authentication: Requires valid X-API-Key header ### Update line item pricing policy with cycle-based discounts - [PUT /api/external/v2/subscription-contracts-update-line-item-pricing-policy](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/updatelineitempricingpolicyv2.md): Sets up advanced pricing rules for a subscription line item that change based on the number of successful orders (cycles). This powerful feature enables loyalty discounts, promotional pricing tiers, and subscribe-and-save models. What are Pricing Policies? Pricing policies define how a product's price changes over the subscription lifetime: - Base Price: Starting price for the product - Cycle Discounts: Price changes after specific numbers of orders - Automatic Application: System applies correct price based on order history Supported Discount Types: - PERCENTAGE: Percentage off base price (e.g., 10% off) - FIXED: Fixed amount off base price (e.g., $5 off) - PRICE: Override with new fixed price (e.g., $19.99) Note: SHIPPING and FREE_PRODUCT types are not supported by this endpoint Cycle Counting: - Cycles start at 1 (first order is cycle 1) - Only successful billing attempts count - Failed payments don't increment the cycle - Current cycle = 1 + count of successful past orders Common Use Cases: 1. Subscribe & Save: 10% off starting from 3rd order 2. Loyalty Tiers: 5% off after 3 orders, 10% after 6 orders 3. Introductory Pricing: First 2 orders at $9.99, then $14.99 4. Promotional Periods: Special price for orders 3-5 Important Limitations: - Maximum 2 cycle discounts per line item - Cycles must have different afterCycle values - Changes apply to future orders only - Existing orders keep their original pricing Prepaid Subscription Handling: For prepaid subscriptions (e.g., pay monthly for weekly delivery): - Base price is per delivery - Current price = base price × delivery frequency - Discounts apply to base price, then multiply Side Effects: - Sends price update email to customer - Recalculates Build-a-Box discounts - Updates product discount synchronization - Triggers shipping price recalculation - Creates detailed activity log Authentication: Requires valid X-API-Key header ### Update product line item price - [PUT /api/external/v2/subscription-contracts-update-line-item-price](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/updatelineitempricev2.md): Updates the base price of a specific product line item within a subscription contract. This endpoint intelligently handles pricing updates while preserving existing discount structures. Key Features: - Updates base price while maintaining discount cycles - Automatically calculates prepaid subscription prices - Preserves existing percentage/fixed discounts - Validates actual price changes before updating - Triggers shipping and discount recalculations - Sends price update notifications to customers Base Price vs Current Price: - Base Price: The unit price before any multipliers - Current Price: Base price × fulfillment multiplier - For monthly billing/weekly delivery: Current = Base × 4 - For pay-per-delivery: Current = Base × 1 Discount Preservation: By default, this endpoint preserves existing discount cycles: - Percentage discounts adjust to new base price - Fixed discounts remain at same dollar amount - Discount schedule (after X cycles) unchanged Prepaid Subscription Handling: For prepaid subscriptions (billing interval > delivery interval): - Automatically calculates fulfillment multiplier - Updates current price accordingly - Ensures correct billing amounts Post-Update Actions: 1. Build-a-Box discount recalculation 2. Product discount synchronization 3. Shipping price updates 4. Customer email notifications 5. Activity log creation Important Notes: - Price changes apply to future orders only - Cannot set price below $0.01 - Maximum 2 discount cycles preserved - No update if price unchanged Authentication: Requires valid X-API-Key header ### Remove multiple products from subscription - [PUT /api/external/v2/subscription-contracts-remove-line-items](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/removelineitems.md): Removes multiple product line items from an existing subscription contract in a single request. Products are removed sequentially, allowing partial success if errors occur. Key Features: - Sequential processing - items removed one by one - Partial success allowed - previous removals persist if later ones fail - Validates each removal against current subscription state - Smart discount cleanup for line-specific discounts - Comprehensive validation for each product removal - Triggers all side effects after each successful removal Processing Order Matters: Items are removed in the order provided: 1. First item validated and removed 2. Second item validated against updated state 3. Continue until all processed or error occurs 4. Returns final subscription state Validation Per Item: - Line item must exist in subscription - At least one recurring product must remain - Build-a-Box min/max quantities maintained - Minimum cycle commitments honored - One-time and free products don't count toward minimum Discount Handling: When removeDiscount=true: - Removes discounts applied ONLY to the removed line - Preserves discounts that apply to multiple lines - Each removal evaluates discounts independently - Build-a-Box discounts auto-adjust based on quantity Side Effects Per Removal: Each successful removal triggers: - Activity log entry created - Customer email sent (except one-time products) - Shipping price recalculation - Build-a-Box discount resync - Product discount adjustments Partial Success Scenarios: If removing 3 items and the 2nd fails: - 1st item: Successfully removed - 2nd item: Fails, error returned - 3rd item: Not attempted - Result: Subscription with 1st item removed Performance Considerations: - Each removal is a separate Shopify API transaction - Multiple emails may be sent to customer - Consider using single remove for 1-2 items - Large batches may timeout - Recommended max: 5-10 items per request Build-a-Box Handling: For Build-a-Box subscriptions: - Validates total quantity after EACH removal - May fail mid-batch if minimum breached - Discounts recalculate after each item - Consider removal order carefully Important Notes: - NOT atomic - no rollback on partial failure - Order of line IDs affects success probability - Customer receives email per removed item - All validations apply as if removing individually - Response shows final state after all attempts Authentication: Requires valid X-API-Key header ### Remove product from subscription - [PUT /api/external/v2/subscription-contracts-remove-line-item](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/removelineitemv2.md): Removes a specific product line item from an existing subscription contract. Can optionally retain prorated discounts associated with the removed product. Key Features: - Validates minimum subscription requirements before removal - Handles discount cleanup for line-specific discounts - Enforces minimum cycle commitments on products - Supports Build-a-Box quantity validation - Automatic retry on concurrent modification conflicts - Email notifications for subscription changes Validation Rules: - At least one recurring subscription product must remain after removal - One-time products and free products don't count toward the minimum - Products with minimum cycle commitments cannot be removed until fulfilled - Build-a-Box subscriptions validate against minimum/maximum quantity rules Discount Handling: When removeDiscount=true (default): - Discounts applied only to the removed line item are deleted - Discounts applied to multiple line items are retained - System automatically identifies which discounts to remove Retry Mechanism: The endpoint automatically retries in these scenarios: - Concurrent modification detected (another process updated the subscription) - Invalid discount code errors (removes problematic discount and retries) - This ensures reliable operation in high-traffic environments Post-Removal Actions: - Activity log created for audit trail - Email notification sent to customer (except for one-time products) - Shipping price recalculated asynchronously - Build-a-Box discounts resynced if applicable - Product-specific discounts resynced Authentication: Requires valid X-API-Key header ### Add multiple products to subscription - [PUT /api/external/v2/subscription-contracts-add-line-items](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/addlineitems.md): Adds multiple product line items to an existing subscription contract in a single request. This batch operation is more efficient than making multiple individual requests and ensures all products are added with consistent processing. Key Features: - Batch addition of multiple products in one API call - All products are added as recurring items (not one-time) - Automatic quantity defaulting (0 or null becomes 1) - Sequential processing with full validation for each item - Returns final subscription state after all additions - Same pricing and discount logic as single-item endpoint Processing Behavior: - Products are added sequentially, not in parallel - If any product fails, previous additions remain - Each product goes through full validation - Existing product handling follows store settings - Activity logs created for each product added Duplicate Product Handling: If a product already exists in the subscription: - With 'updateExistingQuantityOnAddProduct' enabled: Updates quantity - Without setting: Adds as new line item - Setting applies to all products in the batch Pricing and Discounts: Each product receives: - Appropriate selling plan assignment - Discount carry-forward based on store settings - Currency and country-specific pricing - Fulfillment frequency multiplier application Build-a-Box Validation: - Applied if any product has _bb_id attribute - Validates total quantity after all additions - May fail entire batch if limits exceeded Post-Processing: After all products are added: - Build-a-Box discounts recalculated once - Product discounts synchronized - Single email notification sent - Shipping price updated once Important Notes: - Maximum recommended batch size: 10-20 products - Larger batches may timeout - All products become recurring items - Use single-item endpoint for one-time products Authentication: Requires valid X-API-Key header ### Add product to subscription - [PUT /api/external/v2/subscription-contracts-add-line-item](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/addlineitemv2.md): Adds a new product line item to an existing subscription contract. Can add either recurring products that will appear in each order or one-time products that appear only in the next order. Key Features: - Supports both recurring and one-time product additions - Automatically applies appropriate pricing policies based on discount carry-forward settings - Handles duplicate products by updating quantity (if enabled) or adding as new line - Calculates prices based on billing/delivery frequency multipliers - Sends email notifications to customers (unless suppressed) - Creates activity logs for audit trail Pricing Policy Application: The system applies discounts based on the store's discount carry-forward setting: - PRODUCT_PLAN: Uses the discount from the product's selling plan - EXISTING_PLAN: Applies the discount structure from existing subscription items - PRODUCT_THEN_EXISTING: First attempts product plan, falls back to existing if not found One-Time Products: Products added with isOneTimeProduct=true will: - Only appear in the next scheduled order - Be automatically removed after fulfillment - Still attempt to match with appropriate selling plans - Can have subscription discounts applied if store setting allows Duplicate Product Handling: When adding a product that already exists in the subscription: - If store has 'updateExistingQuantityOnAddProduct' enabled and product is not one-time: Updates existing quantity - Otherwise: Adds as a new line item Price Calculation: - Base price is fetched considering contract currency and delivery country - Price is multiplied by fulfillment frequency ratio (billing interval / delivery interval) - Example: Monthly billing with weekly delivery = price × 4 Authentication: Requires valid X-API-Key header ### Add product with custom price to subscription - [PUT /api/external/v2/subscription-contract-add-line-item](https://developers.subscription.appstle.com/external-api-swagger/subscription-products/addlineitemv2_1.md): Adds a new product line item with a custom price override to an existing subscription contract. This endpoint bypasses standard pricing and selling plans to set an exact price. Key Features: - Direct price control - set any price regardless of product pricing - Optional automatic discount application based on shop settings - No selling plan assignment - pure custom pricing - Supports both recurring and one-time products - Email notifications sent to customers - Activity logging for audit trails Custom Pricing Behavior: - Price is set exactly as provided (no calculations) - Overrides any product-level pricing - Not affected by currency or country - No automatic discounts from selling plans - Price remains fixed unless manually updated Shop-Level Discount Application: Despite the method name, this endpoint MAY apply discounts: - Checks shop setting: 'applySubscriptionDiscount' - If enabled, applies shop's default subscription discount - Discount type: PERCENTAGE or FIXED (per shop config) - Creates manual discount: 'PRODUCT_DISCOUNT_[lineId]' - Discount is additional to the custom price Common Use Cases: - Negotiated Pricing: Custom rates for specific customers - Price Matching: Match competitor pricing - Promotional Pricing: Special one-off prices - Bundle Pricing: Custom prices for package deals - Legacy Pricing: Honor old pricing agreements - Test Orders: Zero or nominal pricing for testing Differences from Standard Add: - No selling plan association - No pricing policy rules - No automatic tier discounts - Price doesn't adjust with frequency changes - Manual price management required One-Time Products: When isOneTimeProduct=true: - Product appears only in next order - Automatically removed after fulfillment - Custom price applies to that single order - Shop discount still applies if configured Price Validation: - Must be a positive number - No maximum limit enforced - Can be less than product cost (loss leader) - Currency matches shop's base currency - Decimal precision per currency rules Important Considerations: - No automatic price updates with product changes - Frequency changes don't affect pricing - May bypass minimum order values - Consider margin implications - Document reason for custom pricing Post-Addition Effects: - Customer receives product addition email - Activity log records custom price - Shipping may need recalculation - Order total updates immediately - No impact on other line items Authentication: Requires valid X-API-Key header ## Billing & Payments APIs for handling billing operations, payment processing, and financial transactions related to subscriptions. ### Update billing interval for a subscription contract - [PUT /api/external/v2/subscription-contracts-update-billing-interval](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/updatebillingintervalv2.md): Updates the billing frequency (how often the customer is charged) for a subscription contract. This comprehensive operation recalculates billing dates, adjusts pricing, updates selling plans, and may also modify delivery intervals. Key Features: - Changes billing frequency while maintaining subscription continuity - Automatically adjusts delivery interval when linked to billing - Recalculates next billing date based on store settings - Reprices all line items for the new frequency - Finds and applies matching selling plans - Handles anchor day adjustments for consistent billing - Validates prepaid subscription constraints Billing Interval Types: - DAY: Daily billing (use with caution) - WEEK: Weekly billing (e.g., every 1, 2, 3 weeks) - MONTH: Monthly billing (e.g., every 1, 2, 3 months) - YEAR: Annual billing Validation Rules: - Cannot set the same interval as current (no-op prevention) - For prepaid subscriptions: billing interval must exceed delivery interval - Example: Can't bill monthly if delivering weekly (would be paying for 1 delivery but receiving 4) Next Billing Date Calculation: The system uses sophisticated logic to determine the new billing date: 1. Starts from current or last successful billing date 2. Applies store timezone and order time preferences 3. Ensures date is in the future 4. Respects day-of-week preferences if configured 5. May keep current date if 'enableChangeFromNextBillingDate' is false Side Effects: - Delivery Interval: Updated if currently equal to billing interval - Line Item Pricing: Recalculated based on new frequency multiplier - Selling Plans: Finds and applies best matching plans for products - Anchor Days: Updates billing anchor for consistent scheduling - Email Notifications: Sends 'ORDER_FREQUENCY_UPDATED' to customer - Activity Logs: Records both billing and delivery changes Prepaid vs Pay-Per-Delivery: - Pay-per-delivery: Billing and delivery intervals typically match - Prepaid: Customer pays upfront for multiple deliveries - This endpoint enforces prepaid logic to prevent undercharging Authentication: Requires valid X-API-Key header ### Update next billing date for a subscription contract - [PUT /api/external/v2/subscription-contracts-update-billing-date](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/updatenextbillingdatev2.md): Reschedules the next billing date for an active subscription contract. This endpoint allows you to change when the next order will be created and processed. Key Features: - Updates the next billing date to the specified date - Optionally reschedules all future orders based on the new date - Syncs the updated date to Shopify - Sends confirmation email to customer The rescheduleFutureOrder Parameter: - true (default): Updates the next billing date AND recalculates all future queued orders based on the new date. Use this to shift the entire billing schedule. - false: Only updates the next billing date. Other queued orders remain unchanged. Use this for one-time date adjustments. Important Notes: - The new date must be in the future (with 10 minute grace period) - Date is validated against the shop's timezone - If anchor days are configured, future orders may align to those anchors Process Flow: 1. Validates the contract exists and belongs to the shop 2. Validates the new date is not in the past 3. Updates the billing attempt to the new date 4. Syncs the updated nextBillingDate to Shopify 5. If rescheduleFutureOrder=true, regenerates the queue from the new date 6. Sends confirmation email to customer 7. Records activity log entry Date Format: - Must be ISO 8601 format with timezone - Examples: 2024-03-15T12:00:00Z, 2024-03-15T12:00:00+05:30 - URL encode the date when passing as query parameter Timezone Handling: - The provided date is used as-is for the billing attempt - Validation (past date check) uses the shop's configured timezone - All dates in the response are in UTC (Z suffix) Date Restrictions (Customer Portal Only): When called from customer portal context: - Minimum days from today (skipDaysFromCurrentDate setting) - Maximum days from today (billingDateRestrictToDays setting) - External API calls bypass these restrictions Authentication: Requires valid X-API-Key header ### Update subscription billing attempt - [PUT /api/external/v2/subscription-billing-attempts](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/updatesubscriptionbillingattemptv2.md): Updates an existing subscription billing attempt. This endpoint allows modification of billing attempt details such as billing date, order note, and other attributes. Important Notes: - Only QUEUED billing attempts can be updated - Cannot update attempts that are already processed or failed - Billing attempt must belong to the authenticated shop Authentication: Requires valid X-API-Key header ### Unskip a previously skipped order - [PUT /api/external/v2/subscription-billing-attempts/unskip-order/{id}](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/unskiporderv2.md): Reverses a skip action on a billing attempt. The order will be restored to QUEUED status and will be processed on its scheduled date. Important Notes: - Only works on billing attempts with SKIPPED status - Must be done before the scheduled billing date - Cannot unskip after the billing date has passed - Activity logs are created for audit trail Use Cases: - Customer changes their mind about skipping - Correct accidental skip actions - Restore delivery after resolving temporary issue Authentication: Requires valid X-API-Key header ### Skip the next upcoming order for a subscription - [PUT /api/external/v2/subscription-billing-attempts/skip-upcoming-order](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/skipfirstupcomingorderv2.md): Skips the next scheduled billing attempt for a subscription contract without requiring the billing attempt ID. Automatically finds and skips the earliest QUEUED billing attempt. Convenience Feature: - No need to know the specific billing attempt ID - Automatically finds the next order - Ideal for "skip next order" functionality in customer portals Use Cases: - Simple "skip next delivery" button in customer portal - Quick skip without looking up billing attempt details - One-click skip functionality Authentication: Requires valid X-API-Key header ### Skip a specific order - [PUT /api/external/v2/subscription-billing-attempts/skip-order/{id}](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/skiporderv2.md): Skips a specific billing attempt by ID. The order will not be processed on its scheduled date. This is useful when customers want to skip a particular delivery without canceling their subscription. Important Behaviors: - Only QUEUED billing attempts can be skipped - Skipped orders remain in the system with SKIPPED status - Future orders are not affected - Can be unskipped before the scheduled date if needed - Activity logs are created for audit trail Use Cases: - Customer is on vacation - Customer has excess inventory - Temporary delivery pause for one cycle Authentication: Requires valid X-API-Key header ### Reschedule a billing attempt to a new date - [PUT /api/external/v2/subscription-billing-attempts/reschedule-order/{id}](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/rescheduleorderv2.md): Changes the scheduled billing date for a billing attempt. This allows customers to adjust when their next order will be processed. Rescheduling Options: - Move to earlier date (if allowed by shop settings) - Move to later date - Optionally reschedule all future orders by the same offset Important Behaviors: - Only QUEUED billing attempts can be rescheduled - New date must be in the future - Can affect future billing schedule if rescheduleFutureOrder is true - Activity logs are created for audit trail Use Cases: - Customer wants to delay next delivery - Customer wants to receive order earlier - Adjust delivery schedule to align with customer needs - Coordinate deliveries with customer vacation/travel Authentication: Requires valid X-API-Key header ### Trigger immediate billing for an order - [PUT /api/external/v2/subscription-billing-attempts/attempt-billing/{id}](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/attemptbillingv2.md): Immediately processes a billing attempt, creating an order in Shopify. This bypasses the scheduled billing date and processes the order right away. Important Notes: - Requires shop permission 'enableImmediatePlaceOrder' - Only QUEUED billing attempts can be processed - Creates an actual order in Shopify - Charges the customer's payment method immediately - Cannot be undone once processed Use Cases: - Customer requests early delivery - Process order immediately after resolving payment issue - Manual order processing for special cases Authentication: Requires valid X-API-Key header and shop permission ### Update order note for a billing attempt - [PUT /api/external/v2/subscription-billing-attempts-update-order-note/{id}](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/updateordernotev2_1.md): Updates the order note (customer note) for a billing attempt. This note will be included when the order is created in Shopify. Use Cases: - Add delivery instructions - Include gift messages - Add special handling notes - Store customer preferences for this order Important Notes: - Only works on QUEUED billing attempts - Note is included in the Shopify order when created - Can be updated multiple times before order is processed Authentication: Requires valid X-API-Key header ### Get upcoming orders (top orders) - [GET /api/external/v2/subscription-billing-attempts/top-orders](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/gettopordersv2.md): Retrieves upcoming (queued) billing attempts for a subscription contract or customer. Returns the next scheduled orders that have not yet been processed. Query Options: - Filter by contract ID to see upcoming orders for a specific subscription - Filter by customer ID to see all upcoming orders for a customer - Results are ordered by billing date (earliest first) Use Cases: - Display "Your Next Order" in customer portal - Show upcoming delivery schedule - Calculate upcoming charges - Preview next order contents Authentication: Requires valid X-API-Key header ### Get past orders - [GET /api/external/v2/subscription-billing-attempts/past-orders](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/getpastordersv2.md): Retrieves paginated list of past (processed) billing attempts for a subscription contract or customer. Includes successful orders, failed attempts, and skipped orders. Filter Options: - By contract ID: Get order history for specific subscription - By customer ID: Get all orders across all customer subscriptions - Pagination: Control page size and page number Order Information: - Billing attempt status (SUCCESS, FAILED, SKIPPED) - Shopify order ID for successful attempts - Billing date and processing date - Order total and line items - Error messages for failed attempts Authentication: Requires valid X-API-Key header ### Get past orders report with detailed filtering - [GET /api/external/v2/subscription-billing-attempts/past-orders/report](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/getpastordersreport.md): Retrieves a detailed report of past billing attempts with advanced filtering options. This endpoint provides comprehensive data for analytics, troubleshooting, and reporting purposes. Filter Options: - By status: SUCCESS, FAILED, SKIPPED - By date range: Filter by billing date range - By attempt count: Filter by number of retry attempts - By contract status: Filter by subscription contract status - By contract ID: Get report for specific subscription Response Includes: - Detailed billing attempt information - Shopify exception details for failed attempts (optional) - Retry attempt count - Processing timestamps - Order totals and line items Authentication: Requires valid X-API-Key header ### Associate external payment gateway customer with Shopify customer - [GET /api/external/v2/associate-shopify-customer-to-external-payment-gateways](https://developers.subscription.appstle.com/external-api-swagger/billing-and-payments/associateshopifycustomertoexternalpaymentgateways.md): Links a customer's payment profile from an external payment gateway (Stripe, Braintree, PayPal, Authorize.Net) to their Shopify customer account. This enables Shopify subscription billing to charge payment methods stored in external gateways, which is essential for migrating existing subscriptions or integrating with legacy payment systems. What This Endpoint Does: Creates a connection between a Shopify customer and their corresponding customer profile in an external payment gateway. This allows Shopify's subscription system to send billing requests to the external gateway using the stored payment credentials, effectively enabling subscriptions to bill through payment methods managed outside of Shopify. Supported Payment Gateways: 1. Stripe (paymentGateway=stripe): - Requires: customerProfileId (Stripe customer ID, e.g., cus_xxxxx) - Requires: paymentProfileId (Stripe payment method ID, e.g., pm_xxxxx or card ID) - Links Shopify customer to Stripe customer and stored card/payment method 2. Braintree (paymentGateway=braintree): - Requires: customerProfileId (Braintree customer ID) - Requires: paymentProfileId (Braintree payment method token) - Supports credit cards and PayPal accounts stored in Braintree vault 3. PayPal (paymentGateway=paypal): - Requires: paymentProfileId (PayPal billing agreement ID) - Optional: customerProfileId (not required for PayPal) - Links Shopify customer to PayPal billing agreement 4. Authorize.Net (paymentGateway=authorize_net): - Requires: customerProfileId (Authorize.Net customer profile ID) - Requires: paymentProfileId (Authorize.Net payment profile ID) - Links to Customer Information Manager (CIM) profiles Request Parameters: Required Parameters: - paymentGateway (string): Gateway name - stripe, braintree, paypal, or authorize_net - paymentProfileId (string): Payment method/card ID in the external gateway - customerId OR email (one required): Shopify customer identifier Optional Parameters: - customerProfileId (string): Customer ID in external gateway (required for Stripe, Braintree, Authorize.Net; optional for PayPal) Customer Identification: By Customer ID (recommended): - Provide Shopify customerId if known - Fastest and most reliable method - Avoids ambiguity with duplicate emails By Email: - Provide customer email if customer ID unknown - System looks up Shopify customer by email - If exactly one match: Uses that customer - If multiple matches: Returns error (ambiguous) - If no matches: Creates new Shopify customer with that email Use Cases: 1. Subscription Migration: - Migrating subscriptions from legacy platform to Shopify - Preserving existing payment methods during migration - Avoiding customer disruption by not requiring payment re-entry - Maintaining payment history and customer profiles 2. Payment Gateway Integration: - Using external payment processor for compliance reasons - Leveraging existing payment gateway relationships - Maintaining payment data in external PCI-compliant vault - Integrating with enterprise payment infrastructure 3. Multi-Platform Sync: - Syncing payment methods from other sales channels - Centralizing payment methods across platforms - Enabling subscriptions for existing customer base 4. Custom Checkout Flows: - Building custom subscription checkout with external gateway - Collecting payment via external gateway, then linking to Shopify - Supporting payment methods not natively available in Shopify Process Flow: 1. Customer Lookup: - If customerId provided: Use directly - If email provided: Search for existing Shopify customer - If email not found: Create new Shopify customer 2. Validation: - Validate payment gateway name - Check required parameters for selected gateway - Verify customer belongs to authenticated shop 3. Gateway Association: - Call Shopify GraphQL mutation for gateway-specific association - Link customer profile ID and payment profile ID - Store association in Shopify's payment instrument vault 4. Response: - Return Shopify's raw GraphQL response - Response includes payment instrument ID for future use - Contains success/error details from Shopify API Example Requests: Stripe Example: GET /api/external/v2/associate-shopify-customer-to-external-payment-gateways? paymentGateway=stripe& customerId=12345& customerProfileId=cus_ABC123& paymentProfileId=pm_XYZ789 Braintree with Email: GET /api/external/v2/associate-shopify-customer-to-external-payment-gateways? paymentGateway=braintree& email=customer@example.com& customerProfileId=bt_customer_123& paymentProfileId=bt_card_token_456 PayPal Example: GET /api/external/v2/associate-shopify-customer-to-external-payment-gateways? paymentGateway=paypal& customerId=12345& paymentProfileId=B-12345BILLING67890 Important Considerations: Gateway Setup: - External payment gateway must be installed and configured in Shopify - Gateway must be activated for subscription billing - Appropriate credentials and API keys must be configured Data Validation: - Payment profile IDs are not validated against external gateway - Invalid IDs will be accepted but will fail during actual billing - Test associations before migrating production subscriptions Customer Creation: - If customer doesn't exist and email provided, new customer is created - Created customers have minimal information (just email initially) - Consider adding additional customer details after creation Security: - This endpoint does NOT store or handle actual payment credentials - Only references/tokens to external gateway profiles are used - Payment data remains in external gateway's PCI-compliant vault - Shopify never receives sensitive card data Best Practices: 1. Test First: Test with sandbox/test gateway credentials before production 2. Verify Gateway Active: Ensure external gateway is properly configured in Shopify 3. Use Customer ID: Prefer customerId over email to avoid ambiguity 4. Handle Errors: Implement robust error handling for gateway failures 5. Validate Externally: Verify payment profiles exist in external gateway before associating 6. Document IDs: Keep mapping of Shopify customer IDs to external gateway IDs Migration Workflow Example: For each legacy subscription: 1. Get customer email and Stripe customer ID from legacy system 2. Call this endpoint to link Shopify customer to Stripe customer 3. Create subscription contract in Shopify using returned payment instrument 4. Verify subscription created successfully 5. Mark legacy subscription as migrated 6. Test billing with external gateway Troubleshooting: "More than one customer found for email": - Multiple Shopify customers exist with same email - Solution: Use specific customerId instead of email "Invalid payment gateway": - Gateway name misspelled or unsupported - Solution: Use exact values: stripe, braintree, paypal, authorize_net "customerProfileId required": - Missing required parameter for Stripe/Braintree/Authorize.Net - Solution: Provide customer ID from external gateway Response Format: Returns Shopify's raw GraphQL mutation response containing payment instrument details and success/error information. Related Endpoints: - GET /api/external/v2/subscription-contract-details/shopify/customer/{customerId}/payment-methods - Verify association successful - PUT /api/external/v2/subscription-contracts-update-payment-method - Use associated payment for subscription Authentication: Requires valid X-API-Key header ## Subscription Discounts APIs for managing discounts and promotional codes applied to subscriptions. ### Remove discount from subscription - [PUT /api/external/v2/subscription-contracts-remove-discount](https://developers.subscription.appstle.com/external-api-swagger/subscription-discounts/removediscountv2.md): Removes a specific discount from a subscription contract based on the discount ID. This will affect the pricing of all future orders generated by the subscription. Key Features: - Removes any type of discount: automatic, manual, or code-based - Uses Shopify's draft system for safe removal - Immediate effect on future order pricing - Cannot be undone - discount must be re-applied if needed - Activity log tracks removed discounts Finding Discount IDs: Discount IDs can be found in the subscription contract's discount collection: - Query the subscription contract to see discounts.edges[].node.id - Format: gid://shopify/SubscriptionManualDiscount/123456 - Each discount has a unique ID regardless of type Types of Discounts: - Manual Discounts: Applied via API (percentage, fixed, price) - Code Discounts: Applied using discount codes - Automatic Discounts: Applied by Shopify based on rules - Build-a-Box Discounts: Volume-based discounts - Selling Plan Discounts: Built into the subscription plan Impact on Pricing: When a discount is removed: - Future orders use full price (no discount) - Existing orders are not affected - Other discounts remain active - Shipping prices may be recalculated - Customer sees updated pricing immediately Common Use Cases: - End promotional period discounts - Remove expired or invalid discount codes - Clear discounts before applying new ones - Customer service adjustments - Correct pricing errors Important Notes: - Cannot remove selling plan built-in discounts - No customer notification sent (consider sending separately) - Cannot selectively remove - removes entire discount - Build-a-Box discounts may auto-reapply based on quantity - Some discounts may be required by business rules Post-Removal Considerations: - Customer may notice price increase on next order - May affect customer retention if unexpected - Consider grace periods or notifications - Document reason for removal in your system Authentication: Requires valid X-API-Key header ### Apply discount code to subscription - [PUT /api/external/v2/subscription-contracts-apply-discount](https://developers.subscription.appstle.com/external-api-swagger/subscription-discounts/applydiscountcodev2.md): Applies a Shopify discount code to an existing subscription contract. The discount will be applied to future orders generated by this subscription. Key Features: - Validates discount code through Shopify's discount system - Prevents duplicate discount code applications - Uses database locking to prevent race conditions - Automatically recalculates shipping prices if needed - Creates audit trail through activity logs - Returns updated subscription with discount details Discount Code Validation: - Must be an active Shopify discount code in the store - Must be applicable to subscription orders - Cannot be applied if already active on the subscription - Subject to Shopify's discount rules and restrictions Customer Portal Restrictions: When called from customer portal context: - If 'enableAllowOnlyOneDiscountCode' is enabled, customers cannot apply additional codes - This restriction ensures single discount policy enforcement - External API calls bypass this restriction Concurrency Protection: - Uses database-level locking on the subscription contract - Prevents simultaneous discount applications - Ensures data consistency in high-traffic scenarios Post-Application Effects: - Discount applies to all future orders from the subscription - May trigger shipping price recalculation - Creates 'DISCOUNT_APPLIED' activity log entry - Updates subscription's discount collection Important Notes: - Discount codes are case-sensitive - Invalid or expired codes will return appropriate errors - Discounts stack according to Shopify's combination rules - Some discounts may not be compatible with subscriptions Authentication: Requires valid X-API-Key header ### Add custom discount to subscription - [PUT /api/external/v2/subscription-contracts-add-discount](https://developers.subscription.appstle.com/external-api-swagger/subscription-discounts/adddiscountv2.md): Creates and applies a custom manual discount to an existing subscription contract. This powerful endpoint supports multiple discount types and configurations for flexible pricing strategies. Discount Types: - PERCENTAGE: Percentage off the order (e.g., 10% off) - FIXED: Fixed amount off the order (e.g., $10 off) - PRICE: Override price (sets total to specific amount) Key Features: - Custom discount titles for easy identification - Cycle limits for time-bound promotions - Per-item or subtotal application options - Stacks with other discounts per Shopify rules - Automatic shipping price recalculation - Activity logging for audit trails Application Methods: - Subtotal Discount (appliesOnEachItem=false): Applied to order total after line item calculations - Per-Item Discount (appliesOnEachItem=true): Applied to each line item individually Cycle Limits: - Set recurringCycleLimit to apply discount for specific number of orders - Leave null for unlimited duration - Useful for '3 months at 20% off' promotions Retention Campaigns: This endpoint integrates with cancellation retention workflows: - Can trigger merchant notifications - Tracks discount usage for retention analytics - Helps prevent churn with targeted offers Important Notes: - Discounts apply to future orders only - Cannot modify discounts once applied (must remove and re-add) - Some discount combinations may not be allowed by Shopify - Price overrides should be used carefully Authentication: Requires valid X-API-Key header ## Subscription One-Time Products APIs for managing one-time add-on products that can be purchased alongside recurring subscription items. ### Add one-time product to subscription order - [PUT /api/external/v2/subscription-contract-one-offs-by-contractId-and-billing-attempt-id](https://developers.subscription.appstle.com/external-api-swagger/subscription-one-time-products/saveoneoffbyv2.md): Adds a one-time product (add-on) to a specific subscription order. The product will be included only in the specified billing attempt and will not recur in future orders. This endpoint is idempotent - attempting to add the same product to the same billing attempt will return success without creating duplicates. Important Behaviors: - If the specified billingAttemptId is not valid or not QUEUED, the system will automatically add the product to the next upcoming order - The system prevents duplicate products (same variantId) in the same billing attempt - Products are automatically removed after the associated order is processed - Activity logs are created for audit trails Validation Rules: - Contract must belong to the authenticated shop - Contract must not be frozen (minimum cycles restriction) - At least one QUEUED billing attempt must exist - Variant must be a valid Shopify product variant Use Cases: - Allow customers to add special items to their next delivery - Enable upselling opportunities in customer portals - Programmatically add promotional or seasonal items - Implement "try before you subscribe" features Authentication: Requires valid X-API-Key header that identifies the shop ### Remove one-time product from subscription order - [DELETE /api/external/v2/subscription-contract-one-offs-by-contractId-and-billing-attempt-id](https://developers.subscription.appstle.com/external-api-swagger/subscription-one-time-products/deleteoneoffbyv2.md): Removes a previously added one-time product from a specific subscription order. This permanently deletes the one-time product from the specified billing attempt. The operation is idempotent - attempting to delete a non-existent product will succeed without error. Important Notes: - Only removes the product from the specified billing attempt - Cannot remove products from billing attempts that are already processed - Activity logs are created for audit trails - Returns the updated list of all one-time products for the contract Use Cases: - Allow customers to remove unwanted add-ons before order processing - Clean up cart-like functionality in customer portals - Programmatically manage one-time product selections - Implement "undo" functionality for product additions Business Rules: - Contract must belong to the authenticated shop - The specific combination of contractId + billingAttemptId + variantId identifies the product to remove - No error is thrown if the product doesn't exist (idempotent operation) Authentication: Requires valid X-API-Key header that identifies the shop ### Get one-time products for next upcoming order - [GET /api/external/v2/upcoming-subscription-contract-one-offs-by-contractId](https://developers.subscription.appstle.com/external-api-swagger/subscription-one-time-products/getoneoffforcontractnextorderexternal.md): Retrieves one-time products that will be included in the next scheduled order for a subscription contract. This endpoint specifically returns products associated with the earliest queued billing attempt, making it ideal for showing customers what additional items will be in their next delivery. Key Differences from /subscription-contract-one-offs-by-contractId: - Returns ONLY products for the next upcoming order (not all future orders) - Finds the earliest QUEUED billing attempt by date - Returns empty array if no queued billing attempts exist - Useful for "Your Next Order" previews in customer portals Use Cases: - Display a preview of the next order including one-time add-ons - Calculate the total cost of the upcoming delivery - Show customers their next delivery date with associated one-time items - Allow last-minute modifications before order processing Business Logic: 1. Searches for billing attempts with status = QUEUED 2. Selects the one with the earliest billing date 3. Returns all one-time products for that specific billing attempt 4. Returns empty array if no queued orders exist (e.g., subscription paused/cancelled) Authentication: Requires valid X-API-Key header that identifies the shop ## Subscription Plans APIs for managing subscription plans, pricing tiers, and plan configurations. ### Get all subscription groups - [GET /api/external/v2/subscription-groups](https://developers.subscription.appstle.com/external-api-swagger/subscription-plans/getallsubscriptiongroupsv2external.md): Retrieves a list of all subscription groups (selling plan groups) configured in the store. This endpoint provides a complete overview of all subscription offerings available. Response includes: - All subscription groups with their configurations - Complete selling plan details for each group - Product and variant assignments (as JSON strings) - Discount configurations and tiers - Member restrictions and settings Use Cases: - Display all subscription options in a custom interface - Audit subscription configurations - Export subscription data for analysis - Synchronize with external systems Performance Notes: - Returns all groups in a single response (no pagination) - Response size grows with number of groups and plans - Product/variant lists are JSON-encoded strings within the response Authentication: Requires valid X-API-Key header ### Update subscription group details and product assignments - [PUT /api/external/v2/subscription-groups](https://developers.subscription.appstle.com/external-api-swagger/subscription-plans/updatesubscriptiongroupdetailsv2.md): Updates an existing subscription group (selling plan group) including its name, selling plans configuration, and optionally manages product/variant assignments. This endpoint provides comprehensive update capabilities for both the subscription group structure and its product associations. Key Capabilities: - Update subscription group name - Modify existing selling plan configurations (discounts, frequencies, trials, etc.) - Add or remove products/variants through updateProducts and deleteProducts fields - Cannot add or remove selling plans - only modify existing ones - Automatically handles complex discount transitions for free trials and prepaid plans - Updates delivery profile associations if changed - Triggers asynchronous operations for metafield updates and free product checks Important Notes: - The 'id' field is required and must match an existing subscription group - For each selling plan in subscriptionPlans array, provide 'idNew' with the existing selling plan ID - Plan modifications maintain the same selling plan ID in Shopify - Product/variant updates are processed after group details are updated - Large product updates (allProduct=true) run asynchronously Selling Plan Updates: - Can change discount amounts, types, and cycles - Can modify billing/delivery frequencies - Can add/remove free trials - Can change member restrictions and tags - Can update specific day delivery settings - Can modify min/max cycles Authentication: Requires valid X-API-Key header ### Create a new subscription group (selling plan group) - [POST /api/external/v2/subscription-groups](https://developers.subscription.appstle.com/external-api-swagger/subscription-plans/createsubscriptiongroupv2external.md): Creates a new subscription group with one or more selling plans in Shopify. A subscription group is a container for selling plans that can be applied to products and variants. Each group can contain multiple plans with different frequencies, discounts, and delivery schedules. Key Features: - Create multiple subscription plans within a single group - Configure complex discount tiers (up to 2 levels + custom cycles) - Set up free trials with automatic discount transitions - Define prepaid plans (PAY_AS_YOU_GO_PREPAID) with custom billing cycles - Configure member-only plans with tag-based access control - Set specific delivery dates (e.g., 15th of every month) - Add all products from store or specific collection automatically Discount Configuration: - First discount tier: Applied from a specific cycle (afterCycle1) - Second discount tier: Applied from another cycle (afterCycle2) - Additional cycles: Configure via appstleCycles for complex scenarios - Free trials: Automatically configure 100% discount for trial period Product Assignment: - Assign specific products via productIds field in request body - Assign specific variants via variantIds field in request body - Use isAddAllProduct=true to add all store products - Use collectionId with isAddAllProduct=true to add all products from a collection Authentication: Requires valid X-API-Key header ### Remove products or variants from a subscription group - [PUT /api/external/v2/subscription-groups/{id}/remove-products](https://developers.subscription.appstle.com/external-api-swagger/subscription-plans/deleteproductsorvariantsv2.md): Removes specified products and/or variants from an existing subscription group (selling plan group). This endpoint allows selective removal of products without affecting the group's configuration or other product assignments. Key Features: - Remove multiple products and variants in a single request - Remove all products from a specific collection - Silently ignores products/variants not currently in the group - Preserves subscription group configuration and settings - Updates synchronously and returns the modified group Collection Removal: - When collectionId is provided, fetches and removes all products from that collection - Collection processing is limited to 5000 products maximum - Collection removal is additive to any explicitly specified productIds/variantIds Important Notes: - Removing products does NOT affect existing active subscriptions - Can remove all products, leaving an empty subscription group - Products/variants not in the group are silently ignored - Use numeric IDs without gid:// prefix for products and variants Authentication: Requires valid X-API-Key header ### Add products or variants to an existing subscription group - [PUT /api/external/v2/subscription-groups/{id}/add-products](https://developers.subscription.appstle.com/external-api-swagger/subscription-plans/addproductsorvariants.md): Adds one or more products and/or product variants to an existing subscription group (selling plan group). This endpoint provides a simple way to expand the product catalog eligible for subscription without modifying the group's configuration or existing product assignments. Key Features: - Add multiple products and variants in a single request - Preserves existing product and variant assignments - Maintains the order of products as provided - Updates delivery profiles automatically if needed - Synchronously updates Shopify and returns the updated group - Optional response enhancement with added products information Important Notes: - Product IDs should be numeric Shopify product IDs without the gid:// prefix - Variant IDs should be numeric Shopify variant IDs without the gid:// prefix - Adding products also makes all their variants eligible for subscription - Adding specific variants limits subscription eligibility to those variants only - Duplicate products/variants are handled gracefully by Shopify - URL length limits apply to the comma-separated lists (use bulk endpoint for large additions) - Include 'x-return-short-response: true' header to get only added products/variants information in response Use Cases: - Launch new products with subscription options - Add seasonal items to existing subscription groups - Enable subscription for specific product variants - Expand subscription eligibility without changing plan configurations - Track which products were added in the current request Authentication: Requires valid X-API-Key header ### Remove products or variants from ALL subscription groups - [PUT /api/external/v2/subscription-groups/remove-products](https://developers.subscription.appstle.com/external-api-swagger/subscription-plans/deleteproductsorvariantsinallsubscriptiongroupplan.md): Removes specified products and/or variants from ALL subscription groups in the store. This is a powerful bulk operation that affects every subscription group simultaneously. ⚠️ WARNING: This operation: - Affects ALL subscription groups in your store - Cannot be easily undone - Processes synchronously (may timeout for stores with many groups) - Does NOT affect existing active subscriptions Use Cases: - Discontinuing products from all subscription offerings - Removing seasonal items from all groups - Cleaning up deleted products from subscription groups - Compliance-driven product removals Important Considerations: - Each group is updated individually - If any group update fails, previous groups remain updated - Large operations may take significant time - Consider using individual group removal for better control Authentication: Requires valid X-API-Key header ### Bulk add products or variants to an existing subscription group - [POST /api/external/v2/subscription-groups/{id}/bulk-add-products](https://developers.subscription.appstle.com/external-api-swagger/subscription-plans/bulkaddproductsorvariants.md): Adds multiple products and/or product variants to an existing subscription group (selling plan group) using a JSON request body. This endpoint is ideal for adding large numbers of products/variants that would exceed URL length limits in the query parameter version. Advantages over query parameter endpoint: - No URL length restrictions - Cleaner syntax for large lists - Better for programmatic integrations - Supports the same functionality with improved scalability Behavior: - Identical to the query parameter endpoint in functionality - Adds products/variants to existing assignments - Preserves product order - Updates synchronously and returns the updated group Authentication: Requires valid X-API-Key header ### Get subscription group by ID - [GET /api/external/v2/subscription-groups/{id}](https://developers.subscription.appstle.com/external-api-swagger/subscription-plans/getsubscriptiongroupv2external.md): Retrieves detailed information about a specific subscription group (selling plan group) by its ID. This endpoint provides complete configuration details for a single subscription group. Response includes: - Group name and configuration - All selling plans with complete details - Product and variant assignments - Discount tiers and configurations - Free trial settings - Member restrictions - Delivery and billing frequencies Use Cases: - Display detailed subscription options for editing - Verify configuration before updates - Debug subscription issues - Integration with external systems Authentication: Requires valid X-API-Key header ### Get all selling plans across all subscription groups - [GET /api/external/v2/subscription-groups/all-selling-plans](https://developers.subscription.appstle.com/external-api-swagger/subscription-plans/getallsellingplansv2external.md): Retrieves a flattened list of all selling plans from all subscription groups in the store. This endpoint provides a consolidated view of every subscription plan available, regardless of which group it belongs to. Response includes: - All selling plans with their configurations - Group information for each plan (groupId and groupName) - Complete discount and pricing details - Delivery and billing frequencies - Member restrictions and settings - Free trial configurations Use Cases: - Build a unified subscription selector - Compare all available subscription options - Analyze pricing across all plans - Find specific plan configurations - Generate reports on subscription offerings Differences from /subscription-groups endpoint: - Returns plans as a flat list, not grouped - Each plan includes its parent group information - Easier to search/filter across all plans - Does not include product/variant assignments Authentication: Requires valid X-API-Key header ## Build-a-Box & Bundles APIs for managing customizable product boxes and bundles where customers can select multiple items. ### Generate discount code for bundle - [PUT /api/external/v2/subscription-bundlings/discount/{token}](https://developers.subscription.appstle.com/external-api-swagger/build-a-box-and-bundles/generatediscountv2.md): Generates a discount code for a subscription bundle. This endpoint creates a Shopify discount code that can be applied to bundle subscriptions, typically used during the checkout process. Discount Code Generation: - Creates a unique discount code in Shopify - Associates the discount with the bundle - Configures discount rules and limitations - Sets expiration dates if specified - Applies usage limits if configured Discount Configuration Options: - Discount type (percentage, fixed amount, or free shipping) - Discount value/amount - Minimum purchase requirements - Maximum usage count - Expiration date - Customer eligibility rules Use Cases: - Promotional campaigns for bundles - Welcome discounts for new subscribers - Loyalty rewards for existing customers - Special offers and limited-time promotions - Partner/affiliate discount codes Important Notes: - Discount codes are created in Shopify and follow Shopify's discount rules - Codes can be single-use or multi-use depending on configuration - Expired or depleted codes cannot be reused Authentication: Requires valid X-API-Key header ### Update subscription bundling configuration - [PUT /api/external/v2/subscription-bundling/update](https://developers.subscription.appstle.com/external-api-swagger/build-a-box-and-bundles/getupdatesubscriptionbundling.md): Updates the configuration for one or more subscription bundles (Build-a-Box). This endpoint allows bulk updates to bundle product selections, quantities, and configurations. Subscription Bundling/Build-a-Box: Subscription bundling allows customers to create custom product bundles that are delivered on a recurring basis. Customers can select multiple products to be included in each delivery, creating a personalized subscription box. Update Capabilities: - Modify product selections within a bundle - Update product quantities - Change bundle configuration settings - Bulk update multiple bundles at once Use Cases: - Customer updates their bundle product selections - Swap products in an existing bundle - Adjust quantities for products in the bundle - Programmatically manage bundle configurations Important Notes: - Updates are identified by bundle handle (unique identifier) - Only active bundles can be updated - Product availability is validated before update Authentication: Requires valid X-API-Key header ### Update an existing Build-A-Box subscription bundle - [PUT /api/external/v2/build-a-box](https://developers.subscription.appstle.com/external-api-swagger/build-a-box-and-bundles/updatesubscriptionbundling.md): Updates an existing Build-A-Box subscription bundle with new configuration settings, product selections, pricing rules, or other bundle attributes. This endpoint allows you to modify any aspect of a previously created bundle while maintaining its unique identifier and shop association. What Can Be Updated: - Bundle Information: Name, description, handle, and display settings - Product Configuration: Available products, product pool, and selection rules - Quantity Limits: Minimum and maximum product counts per box - Pricing Settings: Pricing type, discount rules, and promotional offers - Delivery Options: Subscription frequencies and delivery intervals - Business Rules: Product combination rules, category restrictions - Status: Active/inactive state for customer visibility - Customization Options: Allow product swaps, one-time purchases Update Behavior: - The bundle ID must be provided in the request body - Shop ownership is verified - you can only update bundles belonging to your shop - All fields in the request body will update the corresponding bundle properties - Partial updates are supported - only include fields you want to change - The update is atomic - either all changes succeed or none are applied - Existing subscriptions using this bundle are not automatically affected Impact on Active Subscriptions: - Changes to product availability affect future customer selections - Pricing updates apply to new subscriptions but not existing ones by default - Quantity limit changes are enforced on next customer modification - Frequency changes only affect new subscriptions - Deactivating a bundle prevents new subscriptions but maintains existing ones Common Update Scenarios: 1. Add/Remove Products: Update the available product pool 2. Adjust Pricing: Change discount percentages or pricing models 3. Modify Limits: Update minimum/maximum product selection rules 4. Change Frequencies: Add or remove subscription interval options 5. Update Content: Modify bundle name, description, or images 6. Toggle Status: Activate or deactivate bundle availability 7. Refine Rules: Adjust product combination or category restrictions Best Practices: - Verify product availability before adding to the bundle - Test pricing changes with sample calculations - Communicate bundle changes to existing subscribers - Use inactive status for testing changes before making them live - Keep bundle handles consistent for external integrations - Document major changes for customer support reference - Consider seasonal or promotional updates to keep offerings fresh Validation Rules: - Bundle ID is required and must exist - Shop must match the authenticated shop (cannot transfer bundles) - All referenced products must be valid and available - Minimum product count cannot exceed maximum product count - Pricing values must be non-negative - Bundle handle should remain unique across all bundles Authentication: Requires valid X-API-Key header or api_key parameter (deprecated) ### Create a new Build-A-Box subscription bundle - [POST /api/external/v2/build-a-box](https://developers.subscription.appstle.com/external-api-swagger/build-a-box-and-bundles/createsubscriptionbundling.md): Creates a new subscription bundle (Build-A-Box) allowing customers to select and customize products for recurring deliveries. Build-A-Box enables a flexible subscription model where customers can create personalized product boxes. What is Build-A-Box? Build-A-Box is a subscription feature that allows customers to curate their own product bundles by selecting from a predefined set of products. This creates a highly personalized subscription experience where customers have full control over what they receive in each delivery cycle. Key Features: - Product Selection: Customers choose which products to include in their box - Quantity Control: Set minimum and maximum product quantities - Flexible Configuration: Define rules for product combinations - Pricing Models: Support for various pricing strategies (per-item, flat rate, tiered) - Recurring Delivery: Automatic fulfillment based on subscription frequency - Customization Options: Allow product swaps between delivery cycles Configuration Options: - Bundle Settings: - Bundle name and description - Unique handle for identification - Product pool (available products for selection) - Minimum/maximum number of products - Product quantity limits - Pricing Configuration: - Pricing type (per-product, flat rate, or tiered) - Discount rules - Promotional pricing - Currency settings - Delivery Options: - Subscription frequencies (weekly, bi-weekly, monthly, etc.) - Delivery intervals - Cut-off times for order modifications - Shipping methods - Rules and Restrictions: - Product combination rules - Category restrictions - Inventory requirements - Customer eligibility criteria Build-A-Box Types: 1. Open Selection: Customers can choose any products from the available pool 2. Category-Based: Products are organized into categories with selection rules 3. Single Product: Customers select variations of a single product type 4. Tiered Boxes: Different box sizes with varying product counts and pricing Use Cases: - Coffee Subscription: Customers select different coffee blends for monthly delivery - Snack Boxes: Build custom snack boxes from a variety of treats - Beauty Boxes: Choose skincare and makeup products based on preferences - Meal Kits: Select recipes and ingredients for weekly meal planning - Pet Supply Boxes: Customize toys, treats, and supplies for pets - Supplement Subscriptions: Create personalized vitamin and supplement regimens Customer Workflow: 1. Customer discovers Build-A-Box offering 2. Selects products from available options 3. Chooses delivery frequency 4. Reviews pricing and discounts 5. Completes subscription signup 6. Receives recurring deliveries 7. Can modify selections between delivery cycles Important Notes: - Each bundle must have a unique handle for identification - Product availability is validated at creation time - Pricing rules are applied based on bundle configuration - Bundles must be associated with at least one subscription frequency - Inventory levels should be checked for all included products - Bundle status (active/inactive) controls customer visibility Best Practices: - Set clear minimum and maximum product limits - Provide detailed product descriptions and images - Configure appropriate pricing that encourages subscriptions - Offer multiple delivery frequency options - Set reasonable inventory thresholds - Enable customer portal access for subscription management - Test bundle configurations before making them live Authentication: Requires valid X-API-Key header or api_key parameter (deprecated) ### Get bundle details by handle - [GET /api/external/v2/subscription-bundlings/external/get-bundle/{handle}](https://developers.subscription.appstle.com/external-api-swagger/build-a-box-and-bundles/getvalidsubscriptioncustomerv2_1.md): Retrieves complete details for a subscription bundle using its unique handle. This endpoint returns the bundle configuration, included products, pricing, and available subscription options. Bundle Information Returned: - Bundle name and description - Product selections with quantities - Pricing and discounts - Available subscription frequencies - Bundle status and availability - Product images and details Use Cases: - Display bundle details on product pages - Show bundle contents in customer portal - Fetch bundle configuration for cart/checkout - Integration with external systems - Build custom bundle selection interfaces Bundle Handle: The handle is a unique, URL-friendly identifier for the bundle. It's typically generated when the bundle is created and remains constant throughout the bundle's lifecycle. Authentication: Requires valid X-API-Key header ### Get subscription bundle settings (Build-a-Box configuration) - [GET /api/external/v2/subscription-bundle-settings/{id}](https://developers.subscription.appstle.com/external-api-swagger/build-a-box-and-bundles/getsubscriptionbundlesettingsv2.md): Retrieves the configuration settings for subscription bundles (also known as Build-a-Box or customizable subscription boxes). This endpoint returns all settings that control how customers can create and manage their custom subscription bundles. What are Subscription Bundles (Build-a-Box)? Subscription bundles allow customers to create personalized subscription boxes by selecting multiple products from a curated collection. Instead of subscribing to a fixed product, customers build their own custom bundle that gets delivered on a recurring basis. This is perfect for coffee subscriptions, snack boxes, beauty boxes, supplement packs, and any product category where variety and personalization drive customer satisfaction. Bundle Configuration Settings: 1. Product Selection Rules: - Minimum number of products required in bundle - Maximum number of products allowed in bundle - Product categories available for selection - Variant selection constraints - Quantity limits per product - Total bundle value constraints (min/max price) 2. Bundle Behavior: - Allow customers to modify bundle between orders - Lock bundle after first order - Enable automatic product rotation - Allow quantity adjustments - Substitution rules when products unavailable 3. Pricing & Discounts: - Bundle pricing model (fixed price vs. sum of products) - Volume discounts based on bundle size - Tiered pricing structures - Promotional pricing for bundles - Discount application rules 4. UI/UX Settings: - Bundle builder interface layout - Product display format (grid/list) - Images and descriptions shown - Filter and search options - Preview and summary display - Mobile responsiveness settings 5. Fulfillment Options: - Bundling method (ship together vs. separate) - Packaging preferences - Custom box selection - Gift message options - Delivery instructions 6. Customer Experience: - Welcome flow for new bundle subscribers - Modification window before each order - Reminder notifications to update bundle - Recommendation engine settings - Save favorite bundle configurations Common Bundle Types: Coffee Subscription Bundle: - Select 3-5 coffee varieties per month - Choose roast levels, origins, or flavors - Option to rotate selections monthly - Fixed price regardless of selection Snack Box Bundle: - Choose 10 items from 50+ snacks - Category limits (e.g., max 3 sweet, 7 savory) - Dietary restriction filters (vegan, gluten-free) - Tiered pricing based on bundle size Beauty Box Bundle: - Select products from skincare, makeup, haircare categories - Minimum 5 products, maximum 8 products - Total value must be between $40-$100 - Can swap 2 products each month Vitamin/Supplement Bundle: - Build personalized supplement pack - Health goal-based recommendations - Compatibility checking (ingredient interactions) - Fixed monthly price for up to 5 supplements Use Cases: - Configure bundle builder in customer portal - Validate customer bundle selections against rules - Display bundle configuration options during signup - Integrate with checkout to show bundle pricing - Build custom bundle management interfaces - Sync bundle settings with mobile apps - Generate bundle recommendation algorithms Important Notes: - Settings apply to all subscription bundles in the shop - Changes affect new bundles immediately - Existing bundles maintain their original configuration unless migrated - Product availability is checked in real-time during bundle creation - Bundle modifications may have cutoff times before order processing Best Practices: - Set reasonable min/max limits to balance choice and complexity - Provide clear guidance on bundle building process - Use category limits to ensure variety - Enable modification windows to boost engagement - Offer curated bundle templates as starting points - Implement substitution logic for out-of-stock items - Test bundle builder UX across devices Authentication: Requires valid X-API-Key header ### Retrieve a Build-A-Box bundle by ID - [GET /api/external/v2/build-a-box/{id}](https://developers.subscription.appstle.com/external-api-swagger/build-a-box-and-bundles/getsubscriptionbundling.md): Fetches the complete configuration and details of a specific Build-A-Box subscription bundle using its unique identifier. This endpoint returns all bundle settings including products, pricing, rules, and delivery options. What You'll Receive: - Complete Bundle Configuration: All settings and properties - Product Information: Full list of available products with details - Pricing Structure: Discount rules, pricing type, and promotional settings - Delivery Options: Subscription frequencies and delivery intervals - Business Rules: Product limits, combination rules, and restrictions - Status Information: Active/inactive state and timestamps - Customization Settings: Allow one-time purchases, product swaps, etc. Use Cases: 1. Bundle Management: Retrieve current bundle settings for review or editing 2. Integration Sync: Synchronize bundle data with external systems 3. Customer Portal: Display bundle options and configurations 4. Audit & Reporting: Track bundle configurations over time 5. Validation: Verify bundle setup before making changes 6. Cloning: Retrieve settings to duplicate a successful bundle 7. Troubleshooting: Debug subscription issues by reviewing bundle config Response Details: The response includes comprehensive information about the bundle: - Bundle Metadata: ID, shop, name, handle, unique reference - Product Pool: All products available for customer selection - Selection Rules: Min/max product counts, quantity limits - Pricing Configuration: Discount percentages, pricing models - Subscription Options: Available delivery frequencies - Display Settings: Product view styles, custom HTML, button text - Advanced Features: Third-party rules, inventory tracking, selection types - Timestamps: Creation and last update dates Authorization: - You can only retrieve bundles that belong to your authenticated shop - The system verifies shop ownership before returning bundle data - Returns 404 if bundle doesn't exist or doesn't belong to your shop Integration Tips: - Cache bundle data to reduce API calls for frequently accessed bundles - Use this endpoint to verify bundle existence before creating subscriptions - Combine with update endpoint for edit workflows (get → modify → update) - Check the active field to determine if the bundle is available to customers - Review availableProducts array to ensure product inventory availability Performance Considerations: - Response size varies based on number of products in the bundle - Bundles with extensive custom HTML or large product pools return more data - Consider requesting only necessary fields if partial data is sufficient - Use batch operations if retrieving multiple bundles Authentication: Requires valid X-API-Key header or api_key parameter (deprecated) ### Delete a Build-A-Box subscription bundle - [DELETE /api/external/v2/build-a-box/{id}](https://developers.subscription.appstle.com/external-api-swagger/build-a-box-and-bundles/deletesubscriptionbundling.md): Permanently removes a Build-A-Box subscription bundle from your shop. This operation is irreversible and will prevent new customers from subscribing to this bundle. However, existing subscriptions using this bundle will remain active. Important Deletion Rules: 1. Active Subscriptions Check: The system prevents deletion if there are active subscriptions using this bundle 2. Alternative Approach: If active subscriptions exist, you must first deactivate the bundle instead of deleting it 3. Shop Ownership: You can only delete bundles that belong to your authenticated shop 4. Irreversible: Once deleted, the bundle configuration cannot be recovered 5. Clean Deletion: Only bundles with zero associated subscriptions can be permanently removed Deletion Workflow: 1. Request deletion of bundle with ID 2. System checks for shop ownership 3. System counts active subscriptions using this bundle 4. If subscriptions exist → Returns error with subscription count 5. If no subscriptions → Deletes bundle permanently 6. Returns success (204 No Content) When Deletion is Blocked: The system will prevent deletion and return a 400 error if: - One or more active subscriptions are using this bundle - The error message will include the exact count of active subscriptions - Example: "Deleting Build-A-Box is not possible, 47 subscriptions found. You may deactivate the Build-A-Box." Recommended Workflow for Active Bundles: If you want to stop offering a bundle that has active subscribers: 1. Update the bundle to set active: false (this prevents new subscriptions) 2. Monitor existing subscriptions until they naturally expire or are cancelled 3. Migrate customers to a different bundle if needed 4. Delete the bundle once all subscriptions have been resolved Use Cases: - Testing Cleanup: Remove test bundles created during development - Failed Configurations: Delete bundles that were incorrectly set up - Seasonal Offerings: Remove time-limited bundles after the season ends (if no subscriptions) - Product Discontinuation: Clean up bundles for discontinued product lines - Duplicate Bundles: Remove accidentally created duplicate configurations Best Practices: - Check Before Deleting: Always verify no active subscriptions exist - Use Deactivation First: Set bundles to inactive before attempting deletion - Document Changes: Keep records of when and why bundles were deleted - Backup Configuration: Save bundle settings before deletion for potential recreation - Communicate Changes: Inform team members about bundle removals - Consider Archiving: For historical reference, deactivate rather than delete when possible What Happens After Deletion: - Bundle configuration is permanently removed from the database - Bundle ID becomes available for reuse (though not recommended) - Bundle handle becomes available for new bundles - External integrations referencing this bundle will receive 404 errors - Analytics and historical data may reference the deleted bundle ID Error Prevention: Before attempting deletion, you can: 1. Query active subscriptions to check for bundle usage 2. Set the bundle to inactive status first 3. Wait for all subscriptions to complete or migrate customers 4. Then proceed with deletion Authentication: Requires valid X-API-Key header or api_key parameter (deprecated) ### Retrieve Build-A-Box bundle details by handle for customer storefront - [GET /api/external/v2/build-a-box/{handle}](https://developers.subscription.appstle.com/external-api-swagger/build-a-box-and-bundles/getvalidsubscriptioncustomerv2_2.md): Fetches comprehensive Build-A-Box bundle configuration using a user-friendly handle (URL slug) instead of numeric ID. This endpoint is specifically designed for customer-facing storefronts and integration scenarios where you want to reference bundles by their human-readable handles rather than database IDs. Key Differences from GET /{id}: - Lookup Method: Uses bundle handle (e.g., 'premium-coffee-box') instead of numeric ID (e.g., 12345) - Response Format: Returns SubscriptionBundlingResponseV3 with enhanced structure - Customer Focus: Optimized for storefront display and customer selection workflows - Bundle + Subscription: Returns both bundle details AND associated subscription plan information - Public Access: Designed for integration in customer-facing applications What is a Bundle Handle? A handle is a URL-friendly identifier for a bundle: - Format: lowercase letters, numbers, and hyphens only - Example: premium-coffee-selection, monthly-snack-box, beauty-essentials - Stable: Unlike IDs, handles remain consistent across environments - SEO-Friendly: Can be used in customer-facing URLs - Human-Readable: Easy to remember and communicate Response Structure (SubscriptionBundlingResponseV3): json { "bundle": { // Complete bundle configuration "id": 45678, "bundleName": "Premium Coffee Selection", "bundleHandle": "premium-coffee-selection", "description": "...", "products": [...], "pricing": {...}, "active": true }, "subscription": { // Associated subscription plan details "planId": 98765, "frequencies": [...], "deliveryOptions": {...}, "sellingPlan": {...} } } Primary Use Cases: 1. Storefront Integration: Display bundle details on product pages 2. Customer Portal: Allow customers to browse available bundles 3. Landing Pages: Create dedicated pages for specific bundles using handles 4. Marketing Campaigns: Link directly to bundles with memorable URLs 5. Cross-Platform Sync: Use stable handles for multi-platform integrations 6. Mobile Apps: Retrieve bundle data using consistent identifiers 7. External Integrations: Third-party systems can reference bundles by handle When to Use Handle vs ID: - Use Handle when: - Building customer-facing features - Creating shareable URLs - Syncing across environments (dev → staging → prod) - External systems need stable references - SEO and user experience are priorities - Use ID when: - You already have the numeric ID from another API response - Performing administrative operations - Internal system integration - Optimizing for query performance Availability Validation: The endpoint validates that: - Bundle exists and belongs to the specified shop - Bundle has an associated subscription configuration - If validation fails, returns 404 Not Found - Both bundle AND subscription must be present for success response Integration Examples: Storefront Display: javascript // Fetch bundle for display on product page const handle = 'premium-coffee-selection'; const response = await fetch( /api/external/v2/build-a-box/${handle}, { headers: { 'X-API-Key': 'your-api-key' } } ); const { bundle, subscription } = await response.json(); displayBundleOptions(bundle, subscription); Best Practices: - Handle Naming: Use descriptive, SEO-friendly handles - Caching: Cache bundle data with handle as key for better performance - Error Handling: Always check for 404 - bundle may be deleted or deactivated - Environment Sync: Use handles to maintain consistency across environments - URL Structure: Incorporate handles into clean, readable URLs - Documentation: Document handle conventions for your team Performance Considerations: - Handle lookups may be slightly slower than ID lookups - Response includes full bundle + subscription data (larger payload) - Consider caching for frequently accessed bundles - Returns complete product catalog for the bundle Authentication: Requires valid X-API-Key header or api_key parameter (deprecated) ## Product Catalog APIs for managing the product catalog including product information, variants, and inventory. ### Get all product swaps for a shop - [GET /api/external/v2/product-swaps](https://developers.subscription.appstle.com/external-api-swagger/product-catalog/getallproductswaps.md): Retrieves all configured product swap automations for the authenticated shop. Product swaps allow automatic replacement of products in subscription orders based on billing cycles or recurring schedules. What are Product Swaps? Product swaps enable merchants to automatically replace products in subscription orders at specific billing cycles. This is useful for seasonal products, progression paths (e.g., beginner → intermediate → advanced), or variety subscriptions. Key Features: - View all configured swap automations - See source and destination product mappings - Check which billing cycles trigger swaps - Identify recurring vs one-time swaps - Review discount carry-forward settings Swap Configuration Types: - One-Time Swap: Occurs at a specific billing cycle - Recurring Swap: Occurs at every order - Conditional Swap: Based on billing cycle number Use Cases: - Seasonal product rotations (summer → fall → winter products) - Subscription progression (trial → full product) - Variety boxes with automatic product rotation - Product lifecycle management in subscriptions - A/B testing different products in subscriptions Authentication: Requires valid X-API-Key header ### Get product swap variant groups for a contract - [POST /api/external/v2/product-swaps-by-variant-groups/{contractId}](https://developers.subscription.appstle.com/external-api-swagger/product-catalog/getproductswapsbyvariantidv2.md): Retrieves product swap variant groups for the next 10 billing cycles of a specific subscription contract. This endpoint calculates and returns which products will be swapped to in future billing cycles based on configured swap automations. Response Structure: Returns a 2D array (List>): - Outer array: Represents the next 10 billing cycles - Inner arrays: Contains the variant(s) that will be swapped to for that specific cycle - Index 0: Variants for the next (upcoming) billing cycle - Index 1: Variants for the cycle after that - And so on for the next 10 cycles Variant Details: Each variant object includes: - variantId: Shopify variant ID - quantity: Number of units to swap - title: Variant title (e.g., "Medium Roast - 12oz") - image: Product/variant image URL - productTitle: Full product name - productId: Shopify product GID - variantTitle: Full display name combining product and variant titles - swapId: ID of the swap automation rule that triggered this swap How It Works: 1. Takes the current products in the subscription 2. Applies configured swap automations for the next 10 cycles 3. Calculates which products will be swapped based on: - Billing cycle number - Swap rule configurations (forBillingCycle, checkForEveryRecurringOrder) - Rule sequence/priority 4. Returns the projected product lineup for each cycle Use Cases: - Preview upcoming product swaps in customer portals - Show customers their subscription product timeline - Build interactive swap calendars - Display "what you'll receive" for future orders - Debug and verify swap automation configurations Important Notes: - Returns 10 cycles even if no swaps are configured (returns current products) - Multiple variants in an inner array means multiple products will be in that order - Empty inner arrays indicate no products for that cycle (rare edge case) - The swapId can be used to trace which automation rule triggered the swap Authentication: Requires valid X-API-Key header ### Get all one-time products for a subscription contract - [GET /api/external/v2/subscription-contract-one-offs-by-contractId](https://developers.subscription.appstle.com/external-api-swagger/product-catalog/getoneoffsforsubscriptioncontractv2.md): Retrieves all one-time products (add-ons) associated with a specific subscription contract across all billing attempts. One-time products are additional items that customers can add to their subscription orders on a non-recurring basis. Each one-time product is tied to a specific billing attempt and will only be included in that particular order. Key Features: - Returns ALL one-time products across all queued billing attempts - Each product includes the billing attempt ID to identify which order it belongs to - Includes product details: variant ID, quantity, title, image, and price - Products are automatically removed after the associated billing attempt is processed Use Cases: - Display all one-time products added to a subscription across all upcoming orders - Allow customers to review their one-time add-ons in customer portal - Enable merchants to see all one-time products for a contract - Integrate with external systems to manage subscription add-ons Authentication: Requires valid X-API-Key header ### Get a specific product swap by ID - [GET /api/external/v2/product-swaps/{id}](https://developers.subscription.appstle.com/external-api-swagger/product-catalog/getproductswap.md): Retrieves detailed information about a specific product swap automation configuration. This endpoint returns complete details about the source products, destination products, swap triggers, and all associated settings. Response Details: - Complete swap configuration - Source product variants with images and quantities - Destination product variants with images and quantities - Billing cycle triggers and conditions - Discount carry-forward settings - Email notification preferences - Swap status and history Source and Destination Variants: Both source and destination variants are returned as JSON strings containing: - Variant ID - Display name/title - Product image URL - Quantity to swap - Product metadata Swap Timing: - forBillingCycle: If set, swap occurs at this specific cycle number - checkForEveryRecurringOrder: If true, swap happens on every order - updatedFirstOrder: If true, can affect the initial subscription order Discount Handling: - NONE: No discount carried forward - PERCENTAGE: Percentage discount is maintained - FIXED_AMOUNT: Fixed amount discount is maintained - PRICE: Specific price point is maintained Authentication: Requires valid X-API-Key header ### Delete a product swap automation - [DELETE /api/external/v2/product-swaps/{id}](https://developers.subscription.appstle.com/external-api-swagger/product-catalog/deleteproductswap.md): Permanently deletes a product swap automation configuration. Once deleted, the swap will no longer be applied to any subscription orders. Existing subscriptions that have already had products swapped are not affected. Deletion Behavior: - Permanently removes the swap automation - Does not reverse past swaps that have already occurred - Future orders will not have this swap applied - Cannot be undone - swap configuration must be recreated if needed Impact on Subscriptions: - Active Subscriptions: Will continue with current products (no automatic reversion) - Future Orders: Swap will not be applied - Past Orders: Already swapped products remain unchanged - Queued Swaps: Pending swaps for this automation are cancelled When to Delete: - Discontinuing a seasonal product rotation - Removing outdated swap rules - Cleaning up test or experimental swaps - Product lines being discontinued - Correcting misconfigured swaps Important Notes: - This operation is permanent and cannot be undone - Consider deactivating instead of deleting if you might reuse the configuration - Activity logs for past swaps are retained - Customers are not automatically notified of swap deletion Best Practices: - Review affected subscriptions before deletion - Consider communicating changes to affected customers - Export swap configuration if you might need it later - Use deactivation for temporary pauses instead of deletion Authentication: Requires valid X-API-Key header ## Operations & Settings APIs for managing operational settings, configurations, and administrative functions. ### Create a new shipping/delivery profile (V3) - [POST /api/external/v2/delivery-profiles/v3/create-shipping-profile](https://developers.subscription.appstle.com/external-api-swagger/operations-and-settings/createshippingprofilev3external.md): Creates a new shipping or delivery profile for subscription orders using the V3 request format. This is the latest version with the most comprehensive delivery profile configuration capabilities. Enhancements in V3: - Full support for all Shopify delivery profile features - Advanced rate calculation options - Support for weight-based and price-based rates - Enhanced zone and country management - Better handling of delivery conditions and rules Key Features: - Define complex shipping rate structures - Configure multiple delivery methods per zone - Set up conditional rates based on weight, price, or item count - Manage detailed shipping zones with province-level granularity - Full control over delivery profile settings Authentication: Requires valid X-API-Key header ### Create a new shipping/delivery profile (V2) - [POST /api/external/v2/delivery-profiles/v2/create-shipping-profile](https://developers.subscription.appstle.com/external-api-swagger/operations-and-settings/createshippingprofilev2external.md): Creates a new shipping or delivery profile for subscription orders using the V2 request format. This version provides enhanced configuration options for delivery methods, zones, and pricing. Enhancements in V2: - Improved zone configuration - Better support for multiple delivery methods - Enhanced rate definition capabilities - Support for conditional delivery rates Key Features: - Define custom shipping rates per zone - Configure local delivery options - Set up local pickup methods - Manage shipping zones and countries - Assign profiles to specific products or variants Authentication: Requires valid X-API-Key header ### Create a new shipping/delivery profile - [POST /api/external/v2/delivery-profiles/create-shipping-profile](https://developers.subscription.appstle.com/external-api-swagger/operations-and-settings/createshippingprofilev2.md): Creates a new shipping or delivery profile for subscription orders. This endpoint allows you to configure custom shipping rates, delivery methods, and shipping zones for your subscription products. Delivery profiles control how subscription products are shipped to customers. Key Features: - Define custom shipping rates per zone - Configure local delivery options - Set up local pickup methods - Manage shipping zones and countries - Assign profiles to specific products or variants Delivery Method Types: - SHIPPING: Standard shipping with carrier rates or custom rates - LOCAL_DELIVERY: Local delivery service within specific areas - PICKUP: Customer pickup from store locations Important Notes: - Each delivery profile must have a unique name - At least one delivery method is required - Shipping rates can be set per zone and per weight/price range - Profiles can be assigned to subscription products to control their shipping behavior Authentication: Requires valid X-API-Key header ### Replace products in subscriptions in bulk - [POST /api/external/v2/bulk-automations/replace-product](https://developers.subscription.appstle.com/external-api-swagger/operations-and-settings/replaceproductv2.md): Replaces old product variants with new product variants across multiple subscription contracts in bulk. This powerful operation allows merchants to update products in active subscriptions when products are discontinued, reformulated, or repackaged. What is Product Replacement? Product replacement updates the products in active subscriptions by swapping out old variant IDs with new variant IDs. This is commonly needed when: - Products are discontinued and replaced with new versions - Product packaging changes (size, quantity) - Product reformulations or recipe updates - SKU consolidation or reorganization - Seasonal product variations - Price structure changes Key Features: - Bulk Operation: Update thousands of subscriptions simultaneously - Multi-Variant Support: Replace multiple old variants with new ones in single request - Flexible Mapping: One-to-one, many-to-one, or one-to-many variant replacements - Selective or Universal: Target specific subscriptions or all subscriptions - Asynchronous Processing: Large batches processed in background - Price Preservation Options: Maintain existing subscription pricing or update to new prices - Activity Logging: All replacements are logged for audit trail Operation Modes: 1. Specific Subscriptions: Provide subscription contract IDs to update only those subscriptions 2. All Subscriptions: Set allSubscriptions=true to replace products in ALL active subscriptions containing the old variants How It Works: 1. Identify old variant IDs that need to be replaced 2. Identify new variant IDs that will replace them 3. Optionally specify which subscriptions to update (or use allSubscriptions=true) 4. Submit the bulk replacement request 5. System validates all variant IDs exist and are accessible 6. Bulk automation task is created and queued 7. Each subscription is updated with new variants 8. Customers receive updated subscription details 9. Next orders will include the new products Variant ID Mapping: The replacement supports flexible mapping between old and new variants: One-to-One Replacement: json { "oldVariantIds": [111111], "newVariantIds": [222222] } Old variant 111111 is replaced with new variant 222222 Multiple Variants Replacement: json { "oldVariantIds": [111111, 333333, 555555], "newVariantIds": [222222, 444444, 666666] } Each old variant is replaced with its corresponding new variant (by position) Request Structure: json { "subscriptionIds": [ "gid://shopify/SubscriptionContract/123456", "gid://shopify/SubscriptionContract/123457" ] } Query Parameters: - api_key (required): Your API authentication key - allSubscriptions (optional): Set to true to update all subscriptions, false/omit to update only specified IDs - newVariantIds (required): Comma-separated list of new variant IDs (e.g., 222222,444444,666666) - oldVariantIds (required): Comma-separated list of old variant IDs to replace (e.g., 111111,333333,555555) Use Cases: 1. Product Discontinuation: When a product is being discontinued: - Identify replacement product - Map old variant IDs to new variant IDs - Update all subscriptions containing the old product - Notify customers of the change 2. Packaging Updates: When product packaging changes (e.g., 10oz to 12oz): - Create new variant for new package size - Replace old variant across subscriptions - Adjust pricing if needed 3. Product Reformulation: When product recipes or formulas change: - Create new product variant for reformulated version - Bulk replace old formula with new formula - Maintain customer subscription frequency and pricing 4. SKU Consolidation: When consolidating multiple variants into a single SKU: - Map multiple old variant IDs to single new variant ID - Update all affected subscriptions - Simplify inventory management 5. Seasonal Product Rotation: For seasonal subscription boxes: - Replace summer variants with fall variants - Update all active seasonal subscriptions - Maintain subscription continuity Important Considerations: - Pricing Impact: New variants may have different prices - verify pricing strategy - Inventory Levels: Ensure adequate inventory for new variants - Customer Communication: Consider notifying customers before replacement - Variant Compatibility: New variants should be appropriate replacements - One Operation at a Time: Only one bulk operation can run per shop simultaneously - Irreversible: Product replacements cannot be automatically undone (must be manually reversed) - Subscription Contract IDs: Must use Shopify GraphQL ID format Processing Time: - Small batches (1000): Minutes to hours - Processing time depends on number of subscriptions and line items Best Practices: 1. Test First: Test with a small subset of subscriptions before bulk operation 2. Verify Variants: Confirm all variant IDs are correct and products are active 3. Check Inventory: Ensure sufficient stock of new variants 4. Customer Communication: Notify affected customers about product changes 5. Price Review: Review and confirm pricing for new variants 6. Backup Data: Export subscription data before making bulk changes 7. Monitor Progress: Track bulk operation status to completion 8. Audit Trail: Document reason for replacement for future reference Error Scenarios: - Another bulk operation running: 400 error - Invalid variant IDs: Operation may fail or skip invalid variants - Mismatched array lengths: Ensure oldVariantIds and newVariantIds have same count - Product not found: Variants must exist in your Shopify store - Unauthorized access: Can only modify subscriptions belonging to your shop Customer Impact: - Next subscription order will contain new products - Previous orders are not affected - Subscription price may change if new variant has different price - Customer portal reflects the new product immediately - Subscription frequency and schedule remain unchanged Authentication: Requires valid api_key parameter (X-API-Key header support coming soon) ### Hide subscriptions in bulk - [POST /api/external/v2/bulk-automations/hide-subscriptions](https://developers.subscription.appstle.com/external-api-swagger/operations-and-settings/hidesubscriptionsv2.md): Hides multiple subscription contracts from customer view in bulk. This operation allows merchants to quickly hide subscriptions from appearing in the customer portal without canceling or deleting them. What Does 'Hide' Mean? Hiding a subscription makes it invisible to customers in their customer portal while keeping the subscription data intact. The subscription is not deleted or canceled - it's simply hidden from the customer's view. This is useful for: - Temporarily removing subscriptions from customer access - Managing test or dummy subscriptions - Handling subscription disputes or issues - Preparing subscriptions for migration or cleanup Key Features: - Bulk Operation: Process multiple subscriptions in a single request - Non-Destructive: Subscriptions are hidden, not deleted - Reversible: Hidden subscriptions can be unhidden later - Asynchronous Processing: Large batches are processed in the background - Conflict Detection: Prevents multiple simultaneous bulk operations Operation Modes: 1. Specific Subscriptions: Provide a list of subscription contract IDs to hide 2. All Subscriptions: Set allSubscriptions=true to hide all active subscriptions (use with caution) How It Works: 1. Submit a request with subscription IDs or allSubscriptions flag 2. System validates the subscription IDs belong to your shop 3. A bulk automation task is created and queued 4. Each subscription is marked as hidden 5. Subscriptions disappear from customer portal immediately 6. Subscriptions remain in merchant admin for management Request Body Structure: json { "subscriptionIds": [ "gid://shopify/SubscriptionContract/123456", "gid://shopify/SubscriptionContract/123457", "gid://shopify/SubscriptionContract/123458" ] } Use Cases: - Subscription Cleanup: Hide test or duplicate subscriptions created during setup - Customer Service: Temporarily hide problematic subscriptions while resolving issues - Migration Preparation: Hide old subscriptions before migrating to new plans - Dispute Management: Hide subscriptions involved in billing disputes - Seasonal Management: Hide seasonal subscriptions during off-season - Batch Processing: Clean up subscriptions that meet certain criteria Important Notes: - Only one bulk operation can run at a time per shop - If a bulk operation is already in progress, the request will fail with 400 error - Subscription IDs must be in Shopify GraphQL ID format (gid://shopify/SubscriptionContract/xxxxx) - Hidden subscriptions stop appearing in customer portal but remain active for billing - You can unhide subscriptions later through the admin interface - Using allSubscriptions=true will hide ALL subscriptions - use with extreme caution Processing Time: - Small batches (1000): May take several minutes to hours - Progress can be tracked through the bulk automation status endpoint Best Practices: - Always specify exact subscription IDs rather than using allSubscriptions=true - Test with a small batch first before processing large numbers - Keep track of hidden subscription IDs for future reference - Document the reason for hiding subscriptions for audit purposes - Monitor bulk operation status to ensure completion - Consider notifying customers before hiding their subscriptions Workflow Example: 1. Identify subscriptions to hide (e.g., test subscriptions with specific tags) 2. Extract their subscription contract IDs 3. Call this endpoint with the list of IDs 4. Verify 204 No Content response indicating successful queue 5. Monitor processing status through admin or status endpoint 6. Confirm subscriptions are hidden from customer portal Error Scenarios: - Another bulk operation is running: 400 error with message about operation in progress - Invalid subscription IDs: Silently skips invalid IDs, processes valid ones - Unauthorized subscription access: Only subscriptions belonging to your shop are processed - Empty subscription list: Operation completes successfully with no action Authentication: Requires valid api_key parameter (X-API-Key header support coming soon) ### Get cancellation management configuration - [GET /api/external/v2/cancellation-managements/{id}](https://developers.subscription.appstle.com/external-api-swagger/operations-and-settings/getcancellationmanagementv2.md): Retrieves the cancellation management and retention settings for the authenticated shop. These settings control the subscription cancellation flow, retention strategies, and customer feedback collection when subscribers attempt to cancel their subscriptions. What is Cancellation Management? Cancellation management is a retention system that helps merchants reduce subscription churn by understanding why customers cancel and offering alternatives before they leave. It includes cancellation flows, feedback collection, retention offers (discounts, pauses, frequency changes), and automated win-back strategies. Configuration Components: 1. Cancellation Flow Settings: - Enable/disable self-service cancellation in customer portal - Require customer to contact support for cancellation - Multi-step cancellation confirmation process - Cancellation cooldown period (prevent accidental cancellations) - Minimum subscription duration before cancellation allowed - Immediate vs. end-of-billing-cycle cancellation 2. Cancellation Reasons & Feedback: - Predefined cancellation reasons list - Custom cancellation reason options - Required vs. optional feedback - Free-form text feedback field - Rating/satisfaction scale - Exit survey questions - Feedback sent to merchant email/dashboard Common Cancellation Reasons: - Too expensive / Can't afford - Don't use product enough / Have too much inventory - Product quality issues - Switching to competitor - Delivery issues / Shipping problems - Forgot to cancel earlier - Temporary pause needed (moving, travel, etc.) - Product doesn't meet expectations - Customer service issues - Other (with text field) 3. Retention Offers (Save Flow): - Display retention offers before final cancellation - Offer discount (percentage or fixed amount) - Offer free product/gift with next order - Suggest subscription pause instead of cancel - Suggest frequency change (deliver less often) - Offer to skip next order - Offer to swap products - Personalized offers based on cancellation reason Example Retention Logic: Reason: "Too expensive" → Offer: 20% discount for next 3 months → Offer: Switch to smaller/cheaper variant Reason: "Have too much inventory" → Offer: Pause for 1-3 months → Offer: Change from monthly to every 2 months → Offer: Skip next 2 deliveries Reason: "Product quality issues" → Offer: Free replacement on next order → Offer: Try different product variant → Route to customer support 4. UI/UX Configuration: - Cancellation button placement and styling - Warning messages and modal dialogs - Progress indicator for multi-step flow - Retention offer presentation (modal, inline, etc.) - Confirmation messages - Post-cancellation survey 5. Automation & Notifications: - Send cancellation confirmation email - Notify merchant of cancellations - Trigger win-back email campaigns - Schedule feedback review - Alert for high cancellation rate - Integration with CRM/analytics tools 6. Metrics & Analytics: - Track cancellation rate - Categorize cancellation reasons - Measure retention offer acceptance rate - Calculate customer lifetime value at cancellation - Identify churn patterns and trends - A/B test different retention strategies 7. Advanced Features: - Conditional retention offers based on: - Customer lifetime value - Subscription duration - Product type - Cancellation history - Customer segment - Win-back campaigns for cancelled subscribers - Automatic re-engagement emails (30, 60, 90 days post-cancel) - Special offers to reactivate cancelled subscriptions Cancellation Flow Examples: Basic Flow (No Retention): 1. Customer clicks "Cancel Subscription" 2. Confirmation dialog: "Are you sure?" 3. Optional: Select cancellation reason 4. Subscription cancelled immediately or at period end 5. Confirmation email sent Advanced Retention Flow: 1. Customer clicks "Cancel Subscription" 2. "Before you go..." - Select cancellation reason 3. Display personalized retention offer based on reason 4. Customer chooses: Accept offer OR Continue to cancel 5. If continue: Additional offers or final confirmation 6. If still cancelling: Exit survey 7. Cancellation processed 8. Thank you message + feedback confirmation 9. Follow-up email campaign Use Cases: - Configure cancellation flow in customer portal - Customize retention offers and messaging - Analyze cancellation patterns and trends - Build custom cancellation interfaces - Integrate with customer support tools - Generate churn reports and analytics - A/B test different retention strategies - Automate win-back campaigns Important Notes: - Always comply with consumer protection laws regarding cancellation - Make cancellation process clear and accessible (FTC guidelines) - Don't make cancellation unnecessarily difficult - Respect customer's decision to cancel - Use retention offers ethically (not dark patterns) - Store cancellation feedback for product improvement - GDPR/privacy compliance for feedback data Best Practices: - Keep cancellation process simple (2-3 steps max) - Offer genuine value in retention offers - Personalize offers based on cancellation reason - Make pause/skip options prominent - Use cancellation feedback to improve product/service - Set up automated win-back campaigns - Monitor cancellation rate and take action on trends - Train customer support on retention strategies - Test different retention messaging and offers - Honor cancellations promptly and professionally Legal & Compliance: - FTC regulations require easy cancellation (Click-to-Cancel rule) - California automatic renewal law compliance - European consumer protection directives - Clear disclosure of cancellation terms - Process cancellations within legal timeframes - Provide confirmation of cancellation Authentication: Requires valid X-API-Key header ### Get/Search activity logs - [GET /api/external/v2/activity-logs](https://developers.subscription.appstle.com/external-api-swagger/operations-and-settings/getallactivitylogs.md): Retrieves activity logs for all subscription-related events and changes in the authenticated shop. Activity logs provide a comprehensive audit trail of all subscription activities, changes, and system events. What are Activity Logs? Activity logs are detailed records of every action, event, and change that occurs within your subscription system. They capture who made the change, when it happened, what was changed, and the result of the operation. This provides full traceability and audit capabilities for compliance, debugging, and customer support. Log Information Captured: - Entity Information: - Entity ID: The specific subscription, billing attempt, or resource affected - Entity Type: Type of resource (subscription, billing attempt, plan, settings, etc.) - Event Type: Specific action performed (see Event Types below) - Event Source: Origin of the event (customer portal, merchant portal, API, system, etc.) - Event Details: - Status: SUCCESS, FAILURE, or INFO - Timestamp: When the event occurred - Activity By: User or system that triggered the event - Client IP: IP address of the requester (if applicable) - Additional Info: Detailed JSON payload with before/after values and context Entity Types: - SUBSCRIPTION_BILLING_ATTEMPT - Billing and payment attempt events - SUBSCRIPTION_CONTRACT_DETAILS - Subscription contract modifications - SUBSCRIPTION_GROUP_PLAN - Subscription plan changes - SHIPPING_PROFILE - Delivery profile and shipping updates - CANCELLATION_MANAGEMENT - Subscription cancellation events - DUNNING_MANAGEMENT - Payment retry and dunning activities - PRODUCT_SWAP - Product replacement events - FREQUENCY_SWAP - Billing/delivery frequency changes - EMAIL_TEMPLATE - Email template modifications - SHOP_INFO - Shop settings and configuration changes - SUBSCRIPTION_WIDGET_SETTINGS - Widget configuration updates - CUSTOMER_PORTAL_SETTINGS - Portal settings modifications - SUBSCRIPTION_BUNDLING - Bundle and bundling rule changes Event Sources: - CUSTOMER_PORTAL - Changes made by subscribers through the customer portal - MERCHANT_PORTAL - Changes made by merchants in the admin panel - MERCHANT_EXTERNAL_API - Changes made via API by merchants or integrations - SHOPIFY_EVENT - Events triggered by Shopify webhooks - SHOPIFY_FLOW - Events triggered by Shopify Flow automations - SYSTEM_EVENT - Automated system events (scheduled tasks, sync operations) - MERCHANT_PORTAL_BULK_AUTOMATION - Bulk operations initiated from admin panel Common Event Types: - Subscription Changes: CONTRACT_PAUSED, CONTRACT_ACTIVATED, CONTRACT_CANCELLED, CONTRACT_CREATED - Product Changes: PRODUCT_ADD, PRODUCT_REMOVE, PRODUCT_REPLACE, PRODUCT_QUANTITY_CHANGE, PRODUCT_PRICE_CHANGE - Billing Changes: NEXT_BILLING_DATE_CHANGE, BILLING_INTERVAL_CHANGE, BILLING_ATTEMPT_TRIGGERED, BILLING_ATTEMPT_SKIPPED - Delivery Changes: DELIVERY_INTERVAL_CHANGE, SHIPPING_ADDRESS_CHANGE, DELIVERY_METHOD_UPDATED - Payment Changes: PAYMENT_METHOD_UPDATED, SWITCH_PAYMENT_METHODS - Email Events: SEND_UPCOMING_ORDER_EMAIL, SEND_TRANSACTION_FAILED_EMAIL, SEND_SUBSCRIPTION_CREATED_EMAIL - Discount Events: DISCOUNT_APPLIED, DISCOUNT_REMOVED, PRICING_POLICY_DISCOUNT_APPLIED - One-Time Products: ONE_TIME_PURCHASE_PRODUCT_ADDED, ONE_TIME_PURCHASE_PRODUCT_REMOVED Query Parameters and Filtering: You can filter activity logs using query parameters. All filters support standard operations: - equals - Exact match - in - Match any value in list - greaterThan, lessThan - Date range filtering - contains - Partial text match Example Filter Queries: 1. Get all failed billing attempts: ?entityType.equals=SUBSCRIPTION_BILLING_ATTEMPT&eventType.equals=BILLING_ATTEMPT_TRIGGERED&status.equals=FAILURE 2. Get all customer portal changes: ?eventSource.equals=CUSTOMER_PORTAL 3. Get logs for a specific subscription: ?entityId.equals=123456&entityType.equals=SUBSCRIPTION_CONTRACT_DETAILS 4. Get logs within date range: ?createAt.greaterThan=2024-01-01T00:00:00Z&createAt.lessThan=2024-01-31T23:59:59Z 5. Get all cancellation events: ?eventType.equals=CONTRACT_CANCELLED 6. Get all API-triggered changes: ?eventSource.equals=MERCHANT_EXTERNAL_API Pagination: Results are paginated. Use standard Spring Data pagination parameters: - page - Page number (zero-indexed, default: 0) - size - Page size (default: 20, max: 100) - sort - Sort criteria (e.g., createAt,desc or id,asc) Example: ?page=0&size=50&sort=createAt,desc Use Cases: - Audit and Compliance: Track all changes for regulatory compliance and internal auditing - Customer Support: Review subscription history to troubleshoot customer issues - Debugging: Investigate failed operations and system errors - Analytics: Analyze customer behavior and subscription lifecycle patterns - Reporting: Generate reports on subscription changes, cancellations, and modifications - Integration Monitoring: Track API usage and automated workflow executions - Security: Monitor for unusual activity patterns or unauthorized changes Important Notes: - Activity logs are immutable and cannot be modified or deleted via API - Logs are retained according to your subscription plan's retention policy - The additionalInfo field contains detailed JSON with event-specific context - For large exports, consider using pagination and filtering to reduce data transfer - Logs are scoped to your shop - you can only access logs for your own subscriptions - System events may not have an activityBy value as they're automated Response Headers: - X-Total-Count - Total number of matching records - Link - Pagination links (first, last, next, prev) Authentication: Requires valid api_key query parameter with appropriate permissions ## Customer Portal APIs powering the customer-facing portal where subscribers can manage their own subscriptions. ### Regenerate subscription widget scripts - [GET /api/external/v2/theme-settings/regenerate-scripts-for-shop](https://developers.subscription.appstle.com/external-api-swagger/customer-portal/regeneratescriptforshop.md): Triggers regeneration and deployment of subscription widget JavaScript files for the authenticated shop. This endpoint rebuilds the widget scripts that power subscription functionality on your storefront and deploys them to CDN. What Does This Endpoint Do? This endpoint initiates an asynchronous process to regenerate and update the JavaScript files that enable subscription widgets on your store's theme. The widget scripts handle: - Subscription product selection and display - Subscription plan offerings on product pages - Frequency and delivery interval selectors - Subscription pricing display - Add-to-cart subscription functionality - Widget styling and customization When to Use This Endpoint: 1. After Widget Settings Changes: - Modified widget appearance or styling - Changed subscription plan display options - Updated widget text or labels - Altered widget positioning or layout - Changed frequency options display 2. After Theme Customization: - Installed a new theme - Updated existing theme - Made CSS customizations affecting widgets - Changed theme structure requiring widget updates 3. After Plan Configuration Changes: - Added new subscription plans - Modified existing plan details - Changed plan pricing or discounts - Updated plan availability rules 4. Troubleshooting: - Widget not displaying correctly on storefront - Subscription options showing outdated information - Widget functionality broken after theme changes - Script conflicts or errors on product pages - Cache issues preventing updates from showing 5. After App Updates: - Appstle subscription app has been upgraded - New widget features have been released - Bug fixes requiring script updates How It Works: 1. Initiation: API call triggers the script regeneration process 2. Compilation: System compiles widget configuration, theme settings, and subscription plans into optimized JavaScript 3. Deployment: Generated scripts are uploaded to CDN for fast global delivery 4. Cache Invalidation: Old cached versions are invalidated 5. Completion: Updated scripts become available to your storefront (typically within 1-2 minutes) What Gets Regenerated: - Widget JavaScript: Core widget functionality and UI components - Configuration Data: Embedded shop-specific settings and plan information - Styling Rules: Custom CSS and theme-specific styles - Initialization Code: Auto-load and widget mounting logic - Event Handlers: Customer interaction and analytics tracking Process Details: - Asynchronous: The regeneration happens in the background - Non-blocking: Endpoint returns immediately (true on success) - No downtime: Existing widgets continue working during regeneration - Automatic deployment: Scripts are automatically deployed to CDN - Versioning: New script versions don't break existing functionality Expected Behavior: - Endpoint returns true immediately to confirm process started - Script regeneration completes in background (typically 30-90 seconds) - Updated scripts propagate to CDN (1-2 minutes) - Browser cache may need clearing to see changes immediately - Changes visible to customers after cache expiration (varies by browser) Use Cases: - Automated Deployments: Include in CI/CD pipeline after theme updates - Widget Troubleshooting: Force refresh when widget issues occur - Configuration Sync: Ensure widgets reflect latest settings after bulk changes - Theme Migration: Update scripts after moving to new theme - Testing: Regenerate scripts after making configuration changes in staging - Maintenance: Periodic regeneration to ensure optimal performance Important Notes: - Safe to call multiple times (idempotent operation) - No negative impact on existing subscriptions - Does not modify theme files directly - Scripts are hosted on CDN, not in your theme - Changes apply to all store pages using subscription widgets - Browser caching may delay visibility of changes to end users Best Practices: - Call this endpoint after making widget setting changes - Wait 2-3 minutes before testing changes on storefront - Clear browser cache when testing to see latest version - Use in test/staging environment before production - Avoid calling excessively (once per configuration change is sufficient) - Monitor widget functionality after regeneration Troubleshooting: If widgets still don't reflect changes after regeneration: 1. Wait 5 minutes for full CDN propagation 2. Clear browser cache and hard refresh (Ctrl+Shift+R / Cmd+Shift+R) 3. Check browser console for JavaScript errors 4. Verify theme has widget embed code installed 5. Confirm subscription plans are properly configured 6. Test in incognito/private browsing mode Integration Workflows: Theme Update Workflow: 1. Make theme changes 2. Update widget settings if needed 3. Call regenerate-scripts endpoint 4. Wait 2-3 minutes 5. Test widgets on storefront 6. Deploy to production Bulk Configuration Update: 1. Update multiple subscription plans 2. Modify widget appearance settings 3. Call regenerate-scripts once (not after each change) 4. Verify changes propagated correctly Authentication: Requires valid API key via api_key parameter or X-API-Key header ### Get custom CSS for customer portal - [GET /api/external/v2/subscription-custom-csses/{id}](https://developers.subscription.appstle.com/external-api-swagger/customer-portal/getsubscriptioncustomcssv2.md): Retrieves the custom CSS styling configuration for the customer portal. This endpoint returns all custom CSS rules that have been configured to customize the appearance, layout, and branding of the subscription customer portal. What is Custom CSS? Custom CSS allows merchants to fully customize the visual appearance of their customer portal beyond the basic theme settings. This enables complete brand alignment and creates a seamless experience that matches the merchant's main store design. Custom CSS Capabilities: - Layout Customization: - Modify page layouts and spacing - Adjust grid and flexbox configurations - Control responsive breakpoints - Customize navigation and sidebars - Typography: - Custom fonts and font families - Font sizes, weights, and line heights - Letter spacing and text transforms - Heading and paragraph styles - Colors and Branding: - Brand color palette application - Custom background colors and gradients - Button and link styling - Hover and focus states - Border colors and shadows - Component Styling: - Subscription card appearances - Form input styling - Button designs and interactions - Modal and dialog boxes - Navigation menus - Product images and thumbnails - Advanced Features: - CSS animations and transitions - Media queries for responsive design - Pseudo-elements and pseudo-classes - Custom icons using CSS - Transform and filter effects CSS Structure: The returned CSS includes: - Global styles for portal-wide consistency - Component-specific styles - Responsive design rules - Theme overrides - Custom animations - Print styles (optional) Common CSS Selectors Available: css / Portal container / .subscription-portal { } / Subscription cards / .subscription-card { } .subscription-card-header { } .subscription-card-body { } / Buttons / .btn-primary { } .btn-secondary { } .btn-cancel { } / Forms / .form-control { } .form-group { } .form-label { } / Navigation / .portal-nav { } .nav-item { } / Product displays / .product-item { } .product-image { } .product-title { } Use Cases: - Apply custom branding to match main store design - Create unique visual experiences for different customer segments - Implement seasonal or promotional themes - Enhance mobile responsiveness - Add accessibility improvements (high contrast, larger fonts) - A/B test different portal designs - Integrate with design systems - Implement dark mode or theme switching Important Notes: - CSS is sanitized for security (XSS prevention) - Certain properties may be restricted for security reasons - External resources (fonts, images) must use HTTPS - CSS is cached for performance - changes may take a few minutes to propagate - Invalid CSS syntax is automatically filtered out - Some core portal elements have !important styles that cannot be overridden Best Practices: - Use specific selectors to avoid conflicts - Test across different browsers and devices - Keep CSS organized with comments - Use CSS variables for maintainability - Minify CSS for production performance - Consider accessibility in color choices (WCAG compliance) - Provide fallbacks for advanced CSS features Security Considerations: - CSS is sanitized to prevent code injection - External URLs are validated - JavaScript in CSS is blocked (e.g., expression(), behavior()) - Data URIs are validated for malicious content Authentication: Requires valid X-API-Key header ### Send magic link email to customer for portal access - [GET /api/external/v2/subscription-contracts-email-magic-link](https://developers.subscription.appstle.com/external-api-swagger/customer-portal/emailmagiclinkv2.md): Sends an automated email to a customer containing a secure magic link for accessing their subscription management portal. The email is sent using the shop's configured email template and includes a time-limited authentication token. What This Endpoint Does: 1. Validates customer exists and has subscriptions 2. Generates secure portal access token 3. Retrieves shop's email template configuration 4. Sends personalized email with magic link 5. Logs activity for audit trail Magic Link Functionality: What is a Magic Link? A magic link is a special URL containing an encrypted authentication token that allows customers to access their portal without entering a password. Clicking the link automatically logs them in. Link Contents: - Shop's portal URL - Encrypted customer token (2-hour expiration) - Direct access to subscription management - No password required Security: - Token expires in 2 hours - Single customer authentication - Cannot be used by others - Logged for security audit Request Parameters: email (required): - Customer's email address - Must exactly match email in Shopify - Customer must have at least one subscription - Case-sensitive in some systems Email Template Configuration: Template Requirements: - Email template must be configured in Appstle settings - Template type: SUBSCRIPTION_MANAGEMENT_LINK - Template must not be disabled - Template includes shop branding and customization Email Content: - Personalized greeting with customer name - Clickable magic link button/link - Expiration notice (link valid 2 hours) - Shop branding and footer - Optional custom messaging Template Variables: - {customer_name}: Customer's display name - {magic_link}: Portal URL with token - {shop_name}: Store name - {expiration_time}: Token expiry time Use Cases: 1. Customer Self-Service: - "Forgot password" alternative - Quick portal access without account setup - Passwordless authentication flow - Reduce friction for customers 2. Subscription Management Prompts: - "Manage your subscription" emails - Pre-billing reminders with management link - Post-purchase subscription setup - Re-engagement campaigns 3. Customer Support: - Send portal access to customers - Enable self-service during support interactions - Provide instant portal access - Reduce support workload 4. Automated Workflows: - Payment failure recovery emails - Subscription expiration notices - Pause/skip reminders - Renewal notifications 5. Marketing Campaigns: - Subscription feature announcements - New product availability - Loyalty program invitations - Referral program links Process Flow: 1. API receives email parameter 2. Searches subscription database for customer email 3. If not found → Returns 400 error 4. If found → Retrieves customer subscriptions 5. Sorts subscriptions by status (active first) 6. Checks email template configuration 7. If disabled → Returns 400 error with instructions 8. If enabled → Generates magic link token 9. Prepares email with template 10. Sends email via configured provider 11. Logs activity (source: MERCHANT_EXTERNAL_API) 12. Returns success message Response Format: json "Email triggered successfully." Simple string response confirming email queued for delivery. Important Considerations: Customer Validation: - Email MUST exist in subscription database - Customer MUST have at least one subscription - Customers without subscriptions cannot receive link - Returns error if customer not found Email Template Disabled: - If template disabled in settings: Returns error - Error message guides merchant to enable template - Path: "More -> Email Settings" - Template must be explicitly enabled Email Delivery: - Email sent asynchronously - Success response doesn't guarantee delivery - Check email logs for delivery confirmation - Respects shop's email provider settings Multiple Subscriptions: - If customer has multiple subscriptions: Sorts by status - Active subscriptions shown first - Link provides access to ALL customer subscriptions - Portal displays all contracts Activity Logging: - All magic link emails logged - Source: MERCHANT_EXTERNAL_API - Includes timestamp and customer - Viewable in activity logs Integration Examples: Webhook Trigger - Payment Failed: javascript async function handlePaymentFailure(webhook) { const customerEmail = webhook.customer.email; // Send magic link to customer await fetch( /api/external/v2/subscription-contracts-email-magic-link?email=${customerEmail}, { headers: { 'X-API-Key': process.env.APPSTLE_API_KEY } } ); console.log(Magic link sent to ${customerEmail} for payment update); } Customer Support Button: javascript async function sendPortalAccess(customerEmail) { try { const response = await fetch( /api/external/v2/subscription-contracts-email-magic-link?email=${encodeURIComponent(customerEmail)}, { headers: { 'X-API-Key': apiKey }, method: 'GET' } ); if (response.ok) { alert('Portal access email sent to customer!'); } } catch (error) { console.error('Failed to send magic link:', error); } } Best Practices: 1. Validate Email: Check email format before calling API 2. Rate Limiting: Don't spam customers - limit frequency 3. Error Handling: Handle customer not found gracefully 4. User Feedback: Confirm email sent to user 5. Test Template: Ensure email template configured and working 6. Monitor Logs: Check activity logs for delivery issues Common Errors: "Customer Email does not exist": - Email not found in subscription database - Customer has no subscriptions - Email may be misspelled "Email template not found": - SUBSCRIPTION_MANAGEMENT_LINK template not configured - Contact Appstle support to set up template "Email is currently disabled": - Template disabled in Email Settings - Navigate to More -> Email Settings - Enable "Subscription Management Link" email Authentication: Requires valid X-API-Key header ### Generate customer portal authentication token - [GET /api/external/v2/customer-portal-token](https://developers.subscription.appstle.com/external-api-swagger/customer-portal/getcustomerportaltoken.md): 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 ### Get customer portal settings - [GET /api/external/v2/customer-portal-settings/{id}](https://developers.subscription.appstle.com/external-api-swagger/customer-portal/getcustomerportalsettingsv2.md): Retrieves the customer portal configuration and settings for the authenticated shop. The customer portal is the self-service interface where subscribers can manage their subscriptions, update payment methods, modify delivery addresses, and more. What is the Customer Portal? The customer portal is a dedicated web interface that allows your subscribers to manage their subscription accounts independently. This reduces support burden and improves customer experience by enabling self-service subscription management. Settings Returned: - Display Configuration: - Portal theme and branding settings - Custom colors and logo - Layout preferences - Custom CSS selectors - Feature Toggles: - Enable/disable subscription pausing - Enable/disable order skipping - Enable/disable product swapping - Enable/disable frequency changes - Enable/disable quantity modifications - Enable/disable address editing - Enable/disable payment method updates - Enable/disable subscription cancellation - Subscription Management Options: - Maximum pause duration allowed - Minimum subscription duration requirements - Skip limits per billing cycle - Product swap availability - One-time product add-ons - Communication Settings: - Email notification preferences - Custom portal messaging - Support contact information - Help text and instructions - Access Control: - Portal authentication method - Password requirements - Magic link settings - Session duration - Advanced Options: - Custom domain configuration - Redirect URLs - Webhook endpoints - Analytics tracking settings Use Cases: - Display customer portal with correct branding and theme - Determine which features are available to subscribers - Build custom portal interfaces using your settings - Sync portal configuration across systems - Validate subscription management capabilities - Configure third-party integrations Important Notes: - Settings are shop-specific and unique per merchant - Some features may be restricted based on subscription plan - Changes to settings are reflected immediately in the portal - Custom CSS must be valid and secure - Portal URL is typically: shop-domain.com/apps/subscriptions Common Configuration Scenarios: 1. Standard Self-Service Portal: - Allow pausing (up to 3 months) - Allow skipping (max 2 consecutive orders) - Allow frequency changes - Allow quantity updates - Allow address editing - Enable payment method updates - Enable cancellation with feedback 2. Locked-Down Portal (Minimal Self-Service): - Disable pausing - Disable skipping - Disable cancellation (require support contact) - Allow address editing only - Allow payment method updates only 3. Full-Service Portal (Maximum Flexibility): - Enable all subscription management features - Allow unlimited pauses and skips - Enable product swapping - Enable one-time add-ons - Allow subscription splitting/merging - Custom branding and domain Authentication: Requires valid X-API-Key header ## 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