- Additive changes (new endpoints, new response fields, new optional parameters, new values of an existing field) don’t break a client that ignores what it doesn’t know. Parse JSON leniently and don’t treat enum fields as closed lists.
- Entries tagged Action required may need a code change in your integration. Each one says who is affected and what to do.
- The API reference is generated from the live API, so it always shows the current contract. The Admin API base URL is
https://membership-admin.appstle.com, and Storefront API paths start with/memberships/cp/api/.
Partner tokens work on any plan again
Admin API calls made with a scoped partner token work whether or not the store’s plan includes API access. From August 19, 2026, they returned401 with the detail You do not have permission to access the External API. Please contact the Appstle Membership Support team. on a plan without it. Keys a merchant creates under API Access still need a plan that includes API access.Appstle authenticates its connect and verify calls to your app
Appstle’s calls to your/appstle/connect and /appstle/verify endpoints now carry the same headers as its calls to /appstle/approved and your disconnect endpoint: X-Partner-Timestamp and X-Partner-Signature in HMAC-SHA256 mode, and X-Partner-Secret in Partner Secret mode if you gave Appstle an outbound secret. Until now, the Nonce Handshake calls to these two endpoints carried no authentication header, and the Simple Token Exchange call to /appstle/connect carried none in Partner Secret mode.Who is affected: partners whose /appstle/connect or /appstle/verify endpoint accepts requests without checking that they come from Appstle.Action required: none. You can now check these headers on /appstle/connect and /appstle/verify as well.Reference: Authentication: Partner integrations, Partner integration.Admin APIStorefront APIBehavior changeNew fieldsAction required
Plans, billing intervals, selling plan products
Plans report whether they’re excluded from upgrades and downgrades
GET /api/external/v2/subscription-groupsandGET /api/external/v2/subscription-groups/{subscriptionGroupId}returnexcludedFromUpgradeDowngrade(boolean) on each entry insubscriptionPlans.GET /api/external/v2/subscription-contract-details/billing-intervalreturnsexcludedFromUpgradeDowngrade(boolean).GET /memberships/cp/api/subscription-groups/all-selling-plansreturnsexcludedFromUpgradeDowngrade(boolean) on each plan.GET /memberships/cp/api/data/selling-plan-productsaccepts an optionalsellingPlanIdsquery parameter (string). For a signed-in customer, the list now leaves out plans the merchant excluded from upgrades and downgrades. A plan stays in the list when its ID is insellingPlanIds, so pass the IDs of the plans the member is on (separated by|or,) and the member still sees their own plan.
Customers can’t switch into an excluded plan
PUT /memberships/cp/api/subscription-contract-update-variant returns 400 with the title UserGeneratedError:This membership plan isn't available for upgrade or downgrade when a signed-in customer switches to a variant that belongs only to plans the merchant excluded from upgrades and downgrades. A variant in a plan the membership is already on still works. The Admin API call PUT /api/external/v2/subscription-contract-update-variant doesn’t check the exclusion.Who is affected: storefronts that offer every variant of a membership product as an upgrade or downgrade choice.Action required: build the choices from GET /memberships/cp/api/data/selling-plan-products, as above, and handle 400 on the switch by showing the title.Reference: Update line item variant.Reactivating a cancelled membership can retry a billing attempt that ran out of retries
This applies whenPUT /api/external/v2/subscription-contracts-update-status or PUT /memberships/cp/api/subscription-contracts-update-status sets a cancelled membership to ACTIVE, the membership’s last billing attempt failed for a cycle that’s already due after using up the retries set under the store’s Failed Payment Recovery settings, and the membership has no upcoming order to copy. Appstle now retries the failed billing attempt once. If that charge fails, Appstle takes the action the store chose under Once the membership reaches the maximum number of failures, such as cancelling the membership again. Until now, nothing was charged in this case. A store without Failed Payment Recovery settings still charges nothing.Who is affected: integrations and storefront code that set a cancelled membership to ACTIVE.Action required: treat setting a cancelled membership to ACTIVE as a charge. Do it only when the customer has agreed to pay for the cycle they missed.Reference: Update membership contract status (pause/resume/activate), Update membership contract status.Reactivating a cancelled membership retries its failed billing attempt
WhenPUT /api/external/v2/subscription-contracts-update-status or PUT /memberships/cp/api/subscription-contracts-update-status sets a cancelled membership to ACTIVE and the membership’s last billing attempt failed, Appstle tries to charge the customer for the unpaid cycle. Until now, it billed a copy of the membership’s next upcoming order right away. Cancelling deletes the upcoming orders, so often nothing was charged.Now, when the failed billing attempt is for a cycle that’s already due and hasn’t used up the retries set under the store’s Failed Payment Recovery settings, Appstle retries that billing attempt itself and turns its retries back on. If this charge fails too, the store’s Failed Payment Recovery settings decide what happens next, as for any failed renewal. The membership’s activity log shows a Retry Enabled entry. In every other case, Appstle still bills a copy of the next upcoming order, or nothing if there is none.Who is affected: integrations and storefront code that set a cancelled membership to ACTIVE.Action required: treat setting a cancelled membership to ACTIVE as a charge. Do it only when the customer has agreed to pay for the cycle they missed.Reference: Update membership contract status (pause/resume/activate), Update membership contract status.Merchants can revoke the legacy API key
Under API Access in the Appstle admin, the Legacy API Key now has a Revoke button. After a merchant revokes it, every request that sends that key returns401 with Content-Type: application/problem+json and the detail Invalid API key., the same response as any other unknown legacy key (see Authentication errors). Revoking can’t be undone, and Appstle doesn’t issue a replacement legacy key. Keys that start with apst_ aren’t affected.Who is affected: integrations that still send the key shown on the Legacy API Key card.Action required: create an apst_ key under API Access and move your integration to it before the merchant revokes the legacy key.Error responses use appstle.com problem types and hide internal messages
The application/problem+json error responses changed in two ways:- The
typeof an error now starts withhttps://appstle.com/problem/, for examplehttps://appstle.com/problem/problem-with-message. Before, it started with a different base URL. detailno longer carries internal error text. A server error (5xx) has thedetailAn unexpected error occurred. Please try again later.A400for a path or query parameter of the wrong type, such as a contract ID that isn’t a number, has thedetailUnexpected runtime exception. A400for a request body that isn’t valid JSON has thedetailUnable to convert http message.
type URL, or on the text of detail in these errors.Action required: stop matching on type. Branch on status, and on errorKey or title where the body has them. Treat detail in these errors as a generic message.Pickup locations are no longer available to customers
GET /memberships/cp/api/delivery-profiles/get-locations returns 403 with the detail Access is denied for a signed-in customer. Only the merchant’s admin session can call it. Until now, a signed-in customer could.Who is affected: storefront code that loads the store’s pickup locations for customers.Action required: stop calling it from the storefront.Product data for customers covers only products on the Online Store
For a signed-in customer, the Storefront API product calls now cover only products that are active and published to the Online Store sales channel:GET /memberships/cp/api/data/productsandGET /memberships/cp/api/data/selling-plan-productsleave other products out ofproductsandproductHandleData.GET /memberships/cp/api/data/productandGET /memberships/cp/api/data/product-selling-plan-variantreturn200with an empty body for any other product.GET /memberships/cp/api/data/variant-contextual-pricingreturns400with the titleUserGeneratedError:Product is not availablefor a variant of any other product.POST /memberships/cp/api/product-swaps-by-variant-groupsreturns the same400when a variant in the request or in its swap options belongs to any other product.
400 on the pricing and swap calls by showing the title.Reference: Get product details by ID, Get product with selling plans and variants, Search membership-enabled products with pagination, List products attached to selling plans, Get contextual pricing for a variant by currency, Get product swap options by variant.Storefront requests can’t name another customer or store
A Storefront API request that names acustomerId other than the signed-in customer’s returns 403 with the detail Customer does not match the authenticated session. This covers customerId and customer_id in the path (for example GET /memberships/cp/api/subscription-contract-details/shopify/customer/{customerId}/payment-methods), in the query string and in the request body. A request body whose shop names another store returns 403 with the detail Shop does not match the authenticated session.Who is affected: storefront code that sends a customerId or shop that isn’t the signed-in customer’s and the store’s own, for example PUT /memberships/cp/api/subscription-contract-details.Action required: leave customerId and shop out of Storefront API request bodies, or send the signed-in customer’s and the store’s own values. The session already identifies both.Reference: Get customer payment methods, Update membership contract details.One error for every failed partner authentication
connect, initiate-connect, verify, disconnect and status under /api/partner/{partnerId}/ now return the same error for every authentication failure: 400 with the errorKey TOKEN_INVALID and the title UserGeneratedError:Invalid partner credentials. That covers a Partner ID that is wrong or belongs to a deactivated partner, a wrong X-Partner-Secret (or a missing one on connect, initiate-connect and disconnect), and an invalid HMAC signature or a timestamp more than 5 minutes off. Until now, an unknown or deactivated Partner ID returned PARTNER_NOT_FOUND, and each authentication failure had its own title, such as UserGeneratedError:Invalid partner secret.Who is affected: partners whose code branches on PARTNER_NOT_FOUND, or on the title of a TOKEN_INVALID error.Action required: stop handling PARTNER_NOT_FOUND and the old titles. On TOKEN_INVALID with the title UserGeneratedError:Invalid partner credentials., check the Partner ID first, then the secret or HMAC key.Reference: Partner integration.Admin API calls can’t name another store
An Admin API call whoseshop, shopName, shopDomain or shop_domain parameter names a store other than the API key’s store returns 403 with the detail Shop does not match the authenticated session. The API key already identifies the store.Who is affected: integrations that send a shop parameter to the Admin API.Action required: leave shop out of Admin API calls, or send the store domain of the key’s own store.Contract responses return revisionId
Membership contract responses return revisionId (string), the contract’s revision number in Shopify. It appears on the contract reads, for example GET /api/external/v2/subscription-contracts/contract-external/{contractId}, and on the contract-changing calls such as PUT /api/external/v2/subscription-contract-add-line-item and PUT /api/external/v2/subscription-contract-update-variant. The Storefront API contract reads and PUT /memberships/cp/api/subscription-contracts-apply-discount return it too.Storefront calls can change less of a membership
- The Storefront API no longer serves
PUT /memberships/cp/api/subscription-contracts-add-line-item. UsePUT /memberships/cp/api/v2/subscription-contracts-add-line-item, which takescontractId,shop,quantityandvariantId. It doesn’t takeprice. PUT /memberships/cp/api/subscription-contract-detailssaves onlyorderNoteandphone. It ignores every other field in the request body and keeps the stored value.PUT /memberships/cp/api/subscription-billing-attemptschanges onlybillingDateandorderNote, and only on a billing attempt whose status isQUEUED. Otherwise it returns400with the titleInvalid billing attempt status. It returns400with the titleInvalid contractwhencontractIdisn’t the billing attempt’s contract, andInvalid idwhen the billing attempt doesn’t exist.
price, or that changes contract details or billing attempts beyond the order note, phone and billing date.Action required: call the v2 add-line-item path without price. From the storefront, send both orderNote and phone to update contract details, and both billingDate and orderNote to update a queued billing attempt. Each call overwrites both fields with what you send. Handle 400 on the billing attempt call and show the title.Reference: Add line item to contract, Update membership contract details, Update billing attempt.Three subscription bundle endpoints are no longer in the Admin API reference
The Memberships Admin API reference no longer lists these three bundle endpoints, which aren’t part of the Memberships API:GET /api/external/v2/subscription-bundle-settings/{id}GET /api/external/v2/subscription-bundlings/external/get-bundle/{handle}PUT /api/external/v2/subscription-bundlings/discount/{token}
subscription-bundle-settings/{id} still answered on November 1, 2026. But none of the three is documented any more, so don’t build on them.Who is affected: integrations that call these three endpoints.Action required: stop calling them.Contract details return nextActivationDate and pauseDurationCycle
GET /api/external/v2/subscription-contract-detailsandGET /api/external/v2/subscription-customers-detail/valid/{customerId}returnnextActivationDate(date-time) andpauseDurationCycle(integer, the number of billing cycles to pause when the pause option is selected).GET /memberships/cp/api/subscription-contract-details/customer/{contractId},GET /memberships/cp/api/subscription-customers-detail/valid/{id}andPUT /memberships/cp/api/subscription-contract-detailsreturn both fields.
Admin APIPartner FrameworkBehavior changeBreaking changeAction required
Authentication errors, API access on the plan
Failed Admin API authentication returns a 401 that says why
A request to an /api/external/ path with a missing, unknown or revoked API key now returns 401 with Content-Type: application/problem+json. The body has title, status, detail, path and message, and detail names the failed check, for example API key can not be blank. Before, these requests got the generic message Full authentication is required to access this resource.Who is affected: clients that match on the old generic message.Action required: none for most clients. Read detail to tell a bad key from a plan without API access, and log it.The Admin API needs a plan that includes API access
Admin API calls now work only when the store’s Appstle plan includes API access. On a plan without it, every call returns401 with the detail You do not have permission to access the External API. Please contact the Appstle Membership Support team., whichever key it sends. Until now, calls worked whatever the plan. Appstle checks the plan before it checks whether an apst_ key is revoked, so a store without API access gets this message even when its key has been revoked. Scoped partner tokens got this 401 too, until November 1, 2026.Who is affected: integrations on stores whose plan doesn’t include API access.Action required: when a call returns this detail, ask the merchant to add API access to their plan: in the upgrade notice on the API Access page, they click Chat with us.Reference: Authentication errors.Changing the billing date of a membership with a pending upgrade or downgrade needs confirmation
PUT /api/external/v2/subscription-contracts-update-billing-date and PUT /memberships/cp/api/subscription-contracts-update-billing-date accept an optional cancelPendingScheduledChange (boolean) query parameter.If the membership has a scheduled upgrade or downgrade, a call without cancelPendingScheduledChange=true returns 400, and the billing date and the scheduled change stay as they are. The title names the change and its date, for example UserGeneratedError:A membership downgrade is scheduled for …. With true, the scheduled change is cancelled and the billing date changes.Who is affected: integrations that change billing dates on memberships with a scheduled upgrade or downgrade.Action required: handle 400 on this call. Show the title to the person making the change, and send cancelPendingScheduledChange=true only after they confirm that the scheduled change can be cancelled.Reference: Update membership contract billing date, Update next billing date.