Appstle Subscriptions integrates natively with Shopify Flow, Shopify's built-in automation platform. Use Flow to automate subscription management without any API tokens or external authentication — everything runs securely within Shopify's ecosystem.
ℹ️ Why Shopify Flow? Shopify Flow actions run within Shopify's authenticated context, so there's no need for API tokens or credentials. This makes Flow the most secure way to automate subscription operations — perfect for merchants who want powerful automation without managing API keys.
- In the Appstle admin, go to Settings → Integrations → Shopify Flow
- Enable the Shopify Flow integration
- Open the Shopify Flow editor in your Shopify admin
- Create a new workflow using Appstle triggers and actions
Triggers fire automatically when subscription events occur. Use them to start Flow workflows.
| Trigger | Description |
|---|---|
| Subscription Created | Fires when a new subscription contract is created |
| Subscription Activated | Fires when a subscription is activated from paused or cancelled status |
| Subscription Cancelled | Fires when a subscription is cancelled |
| Subscription Paused | Fires when a subscription is paused |
| Subscription Updated | Fires when a subscription is updated (products, quantity, address, etc.) |
| Trigger | Description |
|---|---|
| Subscription Billing Success | Fires when a billing attempt (payment) is successful |
| Subscription Billing Failure | Fires when a billing attempt (payment) fails |
| Upcoming Order Notification | Fires when an upcoming order notification is sent (based on configured buffer days) |
| Trigger | Description |
|---|---|
| Subscription Billing Interval Changed | Fires when the billing frequency is changed |
| Subscription Next Order Date Changed | Fires when the next billing/order date is modified |
All triggers include a full set of subscription and customer properties. Some triggers include additional context-specific fields.
Included with every trigger:
| Property | Type | Description |
|---|---|---|
Subscription ID | Number | Internal subscription contract ID |
GraphQL Subscription ID | String | GraphQL ID of the subscription contract |
Status | String | Current status: ACTIVE, PAUSED, CANCELLED, EXPIRED, FAILED |
Next Billing Date | String | Next billing date in UTC ISO 8601 (yyyy-MM-dd'T'HH:mm:ss'Z'). Empty string if not ACTIVE. |
Billing Interval | String | Billing frequency unit: DAY, WEEK, MONTH, YEAR |
Billing Interval Count | Number | Number of intervals between billings (e.g., 2 + MONTH = every 2 months) |
Delivery Interval | String | Delivery frequency unit: DAY, WEEK, MONTH, YEAR |
Delivery Interval Count | Number | Number of intervals between deliveries |
Original Order ID | Number | ID of the first order. 0 for imported contracts. |
Original Order Name | String | Name of the first order. Empty string for imported contracts. |
Cancel Reason | String | Reason for cancellation (empty string if not cancelled) |
Pause Reason | String | Reason for pause (empty string if not paused) |
Total Successful Orders | Number | Total successfully completed orders for this contract |
Line Items | Array | Array of line items (see Line Items schema below) |
Order Note Attributes | Array | Array of key-value note attributes (see Order Note Attributes schema below) |
Included with every trigger:
| Property | Type | Description |
|---|---|---|
customer_reference | Reference | Shopify customer reference |
Customer Email | Customer's email address | |
Customer Phone | String | Customer's phone number (empty string if not available) |
Customer Display Name | String | Customer's display name (empty string if not available) |
Customer First Name | String | Customer's first name (empty string if not available) |
Customer Last Name | String | Customer's last name (empty string if not available) |
For Subscription Billing Success, Subscription Billing Failure, and Upcoming Order Notification triggers only:
| Property | Type | Description |
|---|---|---|
Billing Attempt ID | Number | ID of the billing attempt |
Billing Attempt Status | String | SUCCESS, FAILURE, PENDING, or SCHEDULED |
Billing Attempt Count | Number | Number of billing attempts |
Billing Date | String | Scheduled billing date (UTC ISO 8601) |
Billing Attempt Time | String | Actual attempt timestamp (UTC ISO 8601) |
For Subscription Billing Success only:
| Property | Type | Description |
|---|---|---|
Recurring Order ID | Number | Order ID from successful renewal |
Recurring Order Name | String | Order name from successful renewal |
order_reference | Reference | Shopify order reference |
For Subscription Updated trigger only:
| Property | Type | Description |
|---|---|---|
Contract Amount | Number | Total line item amount in contract currency |
Contract Amount USD | Number | Total line item amount converted to USD |
The Line Items property is an array of objects, each representing a product line in the subscription:
| Field | Type | Description |
|---|---|---|
lineItemId | String | ID of the line item |
variantId | Float | Shopify variant ID |
graphqlVariantId | String | GraphQL variant ID |
productId | ID | Shopify product ID (GraphQL format) |
quantity | Int | Quantity |
graphqlSellingPlanId | String | Selling plan ID associated with this line |
sellingPlanName | String | Selling plan name |
customAttributes | Array | Key-value custom attributes on the line item |
The Order Note Attributes property is an array of key-value pairs:
| Field | Type | Description |
|---|---|---|
key | String | Attribute key |
value | String | Attribute value |
Actions are operations you can perform on subscriptions from within a Flow workflow.
| Action | Description | Required Fields |
|---|---|---|
| Add Line Item | Add a product to a subscription | contract_id, product_variant_id, quantity |
| Remove Line Item | Remove a product from a subscription | contract_id, line_id |
| Update Line Item Quantity | Change product quantity | contract_id, line_id, quantity |
| Update Line Item Price | Change product price | contract_id, line_id, base_price |
| Update Line Item Attributes | Update custom attributes on a line item | contract_id, line_id, attributes (JSON) |
| Replace Variant | Swap a product variant for another | contract_id, old_variant_id, new_variant_id |
| Action | Description | Required Fields |
|---|---|---|
| Update Subscription Status | Set status to Active, Paused, or Cancelled | contract_id, status |
| Hide Subscription | Hide from customer portal | contract_id |
| Merge Subscriptions | Combine two subscriptions into one | source_contract_id, destination_contract_id |
| Split Subscription | Split into separate subscriptions | contract_id, line_ids |
| Update Selling Plan | Change the selling plan for a line item | contract_id, line_id, selling_plan_id |
| Update Order Note | Update the order note | contract_id, order_note |
| Update Note Attributes | Update custom note attributes | contract_id, note_attributes (JSON) |
| Action | Description | Required Fields |
|---|---|---|
| Update Billing Interval | Change billing frequency (e.g., monthly → weekly) | contract_id, billing_interval_count, billing_interval |
| Update Frequency by Selling Plan | Change frequency using an existing selling plan | contract_id, selling_plan_id |
| Update Billing Date | Reschedule the next billing date | contract_id, next_billing_date (ISO 8601) |
| Skip Order | Skip the next scheduled order | contract_id, line_id |
| Attempt Billing | Trigger immediate billing/order placement | contract_id or billing_attempt_id |
| Update Max Cycles | Set maximum billing cycles | contract_id, max_cycles |
| Update Min Cycles | Set minimum billing cycles | contract_id, min_cycles |
| Action | Description | Required Fields |
|---|---|---|
| Apply Discount Code | Apply a discount code to a subscription | contract_id, discount_code |
| Remove Discount | Remove a discount from a subscription | contract_id, discount_id |
| Update Pricing Policy | Update pricing policy with cycle-based discounts | contract_id, base_price |
| Action | Description | Required Fields |
|---|---|---|
| Update Delivery Interval | Change delivery frequency | contract_id, delivery_interval_count, delivery_interval |
| Update Delivery Method | Change the shipping method | contract_id, delivery_method_title |
| Update Delivery Price | Change shipping price | contract_id, delivery_price |
| Update Shipping Address | Update delivery address | contract_id, address1, city, country_code |
| Action | Description | Required Fields |
|---|---|---|
| Update Payment Method | Send payment method update to customer | contract_id |
All actions return output fields that can be used in subsequent Flow steps. Every action returns at minimum a success_message field indicating the result of the operation.
Detailed input and output fields for each action. Use the summary tables above for quick reference.
Add a product variant to an existing subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
product_variant_id | String | ✅ | Shopify product variant ID to add |
quantity | String | ✅ | Quantity to add |
is_one_time_product | String | "true" or "false" — add as a one-time (non-recurring) line item. Default: "false" |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
product_variant_id | String | Variant ID that was added |
quantity | String | Quantity added |
is_one_time_product | String | Whether the item was added as one-time |
success_message | String | Result message |
Remove a product from a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
line_id | String | ✅ | Line item ID to remove |
remove_discount | String | Whether to remove the discount associated with this line item |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
line_id | String | Line item ID that was removed |
remove_discount | String | Whether discount was removed |
success_message | String | Result message |
Change the quantity of a product in a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
line_id | String | ✅ | Line item ID |
quantity | String | ✅ | New quantity |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
line_id | String | Line item ID |
quantity | String | Updated quantity |
success_message | String | Result message |
Change the price of a product in a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
line_id | String | ✅ | Line item ID |
base_price | String | ✅ | New base price |
remove_pricing_policy | Boolean | Whether to remove the existing pricing policy. Default: false |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
line_id | String | Line item ID |
base_price | String | Updated price |
remove_pricing_policy | Boolean | Whether pricing policy was removed |
success_message | String | Result message |
Update custom attributes on a line item.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
line_id | String | ✅ | Line item ID |
attributes | String | ✅ | JSON array of key-value pairs |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
line_id | String | Line item ID |
success_message | String | Result message |
Swap a product variant for another in a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
old_variant_id | String | ✅ | Comma-separated variant IDs to replace |
new_variant_id | String | ✅ | Comma-separated variant IDs with optional quantities (e.g., 11111:2,22222:1) |
old_line_id | String | Specific line ID to replace (use when multiple lines have the same variant) | |
carry_forward_discount | String | Whether to carry the existing discount to the new variant |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
old_variant_id | String | Variant IDs that were replaced |
new_variant_id | String | New variant IDs |
success_message | String | Result message |
Set a subscription's status to Active, Paused, or Cancelled.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
status | String | ✅ | ACTIVE, PAUSED, or CANCELLED |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
status | String | Updated status |
success_message | String | Result message |
Hide a subscription from the customer portal.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
success_message | String | Result message |
Combine two subscriptions into one.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
source_contract_id | String | ✅ | Contract ID to merge from |
destination_contract_id | String | ✅ | Contract ID to merge into |
Output Fields:
| Field | Type | Description |
|---|---|---|
source_contract_id | String | Source contract ID |
destination_contract_id | String | Destination contract ID |
success_message | String | Result message |
Split specific line items into a new subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
line_ids | String | ✅ | Comma-separated line item IDs to move |
attempt_billing | String | Whether to immediately bill the new contract after splitting |
Output Fields:
| Field | Type | Description |
|---|---|---|
original_contract_id | String | Original contract ID |
new_contract_id | String | Newly created contract ID |
line_ids_moved | String | Line item IDs that were moved |
success_message | String | Result message |
Change the selling plan for a line item.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
line_id | String | ✅ | Line item ID |
selling_plan_id | String | ✅ | New selling plan ID |
selling_plan_name | String | Display name for the new selling plan |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
line_id | String | Line item ID |
selling_plan_id | String | Updated selling plan ID |
success_message | String | Result message |
Update the order note on a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
order_note | String | ✅ | New order note text |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
success_message | String | Result message |
Update custom note attributes on a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
note_attributes | String | ✅ | JSON array of key-value pairs |
overwrite_existing | Boolean | true to replace all existing attributes; false to merge with existing. Default: false |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
attributes_count | Number | Number of attributes after update |
overwrite_existing | Boolean | Whether existing attributes were overwritten |
success_message | String | Result message |
Change the billing frequency.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
billing_interval_count | String | ✅ | Number of intervals between billings |
billing_interval | String | ✅ | Interval unit: DAY, WEEK, MONTH, YEAR |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
billing_interval_count | String | Updated interval count |
billing_interval | String | Updated interval unit |
success_message | String | Result message |
Change billing and delivery frequency using an existing selling plan.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
selling_plan_id | String | ✅ | Selling plan ID to apply |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
selling_plan_id | String | Applied selling plan ID |
selling_plan_name | String | Selling plan name |
billing_interval_count | String | Updated billing interval count |
billing_interval | String | Updated billing interval unit |
delivery_interval_count | String | Updated delivery interval count |
delivery_interval | String | Updated delivery interval unit |
success_message | String | Result message |
Reschedule the next billing date.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
next_billing_date | String | ✅ | New billing date (ISO 8601) |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
next_billing_date | String | Updated billing date |
success_message | String | Result message |
Skip (or unskip) the next scheduled order.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
line_id | String | ✅ | Line item ID |
is_skip | Boolean | true to skip, false to unskip. Default: true |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
line_id | String | Line item ID |
is_skip | Boolean | Whether the order was skipped |
success_message | String | Result message |
Trigger immediate billing/order placement.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅* | Subscription contract ID (*one of contract_id or billing_attempt_id required) |
billing_attempt_id | String | ✅* | Billing attempt ID (*alternative to contract_id) |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
success_message | String | Result message |
Set the maximum number of billing cycles.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
max_cycles | String | ✅ | Maximum billing cycles |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
max_cycles | String | Updated max cycles |
success_message | String | Result message |
Set the minimum number of billing cycles.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
min_cycles | String | ✅ | Minimum billing cycles |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
min_cycles | String | Updated min cycles |
success_message | String | Result message |
Apply a discount code to a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
discount_code | String | ✅ | Discount code to apply |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
discount_code | String | Applied discount code |
success_message | String | Result message |
Remove a discount from a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
discount_id | String | ✅* | Discount ID to remove (*one of discount_id or discount_code required) |
discount_code | String | Discount code to remove (alternative to discount_id) |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
discount_id | String | Removed discount ID |
success_message | String | Result message |
Update pricing policy with cycle-based discounts.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
base_price | String | ✅ | Base price for the line item |
line_id | String | Specific line item ID (if not provided, applies to all lines) | |
cycles | String | JSON defining cycle-based pricing adjustments | |
overwrite_existing | Boolean | Whether to replace existing pricing policy or merge. Default: false |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
line_id | String | Line item ID |
base_price | String | Updated base price |
success_message | String | Result message |
Change the delivery frequency.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
delivery_interval_count | String | ✅ | Number of intervals between deliveries |
delivery_interval | String | ✅ | Interval unit: DAY, WEEK, MONTH, YEAR |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
delivery_interval_count | String | Updated interval count |
delivery_interval | String | Updated interval unit |
success_message | String | Result message |
Change the shipping method on a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
delivery_method_title | String | ✅ | Shipping method title |
delivery_method_code | String | Shipping method code | |
delivery_method_presentment_title | String | Customer-facing title for the shipping method | |
delivery_method_id | String | Specific delivery method ID |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
delivery_method_title | String | Updated method title |
delivery_method_code | String | Updated method code |
success_message | String | Result message |
Change the shipping price on a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
delivery_price | String | ✅ | New shipping price |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
delivery_price | String | Updated shipping price |
success_message | String | Result message |
Update the delivery address on a subscription.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
address1 | String | ✅ | Street address |
city | String | ✅ | City |
country_code | String | ✅ | Two-letter country code (e.g., US, CA) |
address2 | String | Apartment, suite, etc. | |
province | String | State/province name | |
province_code | String | State/province code (e.g., CA, ON) | |
zip | String | Postal/ZIP code | |
country | String | Full country name | |
first_name | String | Recipient first name | |
last_name | String | Recipient last name | |
phone | String | Recipient phone number | |
company | String | Company name | |
location_id | String | Shopify location ID | |
method_type | String | Delivery method type |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
address1 | String | Updated street address |
city | String | Updated city |
country_code | String | Updated country code |
success_message | String | Result message |
Send a payment method update request to the customer.
Input Fields:
| Field | Type | Required | Description |
|---|---|---|---|
contract_id | String | ✅ | Subscription contract ID |
Output Fields:
| Field | Type | Description |
|---|---|---|
contract_id | String | Subscription contract ID |
success_message | String | Result message |
Trigger: Subscription Billing Failure Condition: Check if this is the 3rd consecutive failure Action: Update Subscription Status → PAUSED
Trigger: Subscription Billing Success Condition: Current billing cycle ≥ 6 Action: Apply Discount Code → LOYAL10
Trigger: Subscription Cancelled Condition: Subscription value > $100/month Action: Send Slack notification (via Shopify Flow's Slack connector)
Trigger: Scheduled (monthly, via Shopify Flow's scheduler) Action: Replace Variant → swap summer product for winter product
Use these values for billing_interval and delivery_interval fields:
DAYWEEKMONTHYEAR
Use these values for the status field:
ACTIVEPAUSEDCANCELLED
All date fields use ISO 8601 format: 2026-03-15T10:00:00Z
For attributes and note_attributes fields, use JSON array format:
[
{"key": "gift_message", "value": "Happy Birthday!"},
{"key": "delivery_instructions", "value": "Leave at door"}
]old_variant_id: Comma-separated variant IDs to replace (e.g.,12345,67890)new_variant_id: Comma-separated variant IDs with optional quantities (e.g.,11111:2,22222:1)
- Shopify Flow is available on Shopify Basic plan and above
- Flow actions require the Appstle Subscriptions app to be installed and the Flow integration enabled
- The Attempt Billing action requires additional permission — contact support to enable
- All actions are logged in the subscription activity log with source
SHOPIFY_FLOW