---
title: Migrate to the SubscriptionContractCalculation API
description: >-
  Learn how to migrate from the SubscriptionDraft API to the new
  SubscriptionContractCalculation API for managing subscription contracts.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/purchase-options/subscriptions/contracts/migrate-to-subscription-calculation-api
  md: >-
    https://shopify.dev/docs/apps/build/purchase-options/subscriptions/contracts/migrate-to-subscription-calculation-api.md
---

# Migrate to the Subscription​Contract​Calculation API

This guide walks you through migrating from the [SubscriptionDraft](https://shopify.dev/docs/api/admin-graphql/latest/objects/SubscriptionDraft) API to the new `SubscriptionContractCalculation` API for managing [subscription contracts](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/contracts).

**Early access:**

This API is in early access. Send feedback to <subscriptions-calculate-api-early-access@shopify.com>.

***

## Requirements

* Access scope: [`write_own_subscription_contracts`](https://shopify.dev/docs/api/usage/access-scopes).
* API version: `2026-10`.

***

## What's changing and why

The new API integrates with Shopify's unified checkout and provides the following benefits:

* **Simplified API surface**: Contract mutations are consolidated into three calculate operations plus a shared commit.
* **Consistent pricing**: Tax and discount calculations align with checkout.
* **Function support**: [Cart transforms](https://shopify.dev/docs/api/functions/latest/cart-transform) and [delivery customizations](https://shopify.dev/docs/api/functions/latest/delivery-customization). Other [Shopify Functions](https://shopify.dev/docs/apps/build/functions) will be supported in later releases.
* **Accurate cost breakdown**: Totals for lines, delivery, taxes, duties, and discounts are available through the API.

The following table summarizes the main differences between `SubscriptionDraft` and the new `SubscriptionContractCalculation` API.

| Aspect | SubscriptionDraft | SubscriptionContractCalculation |
| - | - | - |
| **Approach** | Multi-step draft mutations | Single contract calculation |
| **Processing** | Synchronous | Asynchronous (requires polling) |
| **State management** | Server maintains draft state | Client provides desired state; omitted fields are preserved on update |
| **Webhooks** | None | Webhooks on success or failure |

***

## Understand the new API model

### From drafts to contract calculations

With the current `SubscriptionDraft` API, you create a draft, apply changes through multiple mutations, and then commit the draft. With the new `SubscriptionContractCalculation` API, you submit the desired state in a single request. The server calculates pricing, applies taxes, executes functions, and returns an immutable result snapshot. On contract updates, any field you omit is left unchanged — you don't need to resend the entire contract.

### Asynchronous processing

Calculations run asynchronously. You can poll for results or subscribe to [webhooks](#webhook-integration). Here's the flow:

1. Call the calculate mutation.
2. Receive a `SubscriptionContractCalculationPending` response.
3. Poll the `subscriptionContractCalculation` query, or wait for a webhook.
4. Receive a `SubscriptionContractCalculationSuccess` or `SubscriptionContractCalculationFailure` response when complete.
5. Call `subscriptionContractCalculationCommit` to apply the changes.

### Feature flags

The following Boolean fields control contract calculation behavior:

| Field | Location | Description |
| - | - | - |
| `withMerchandiseCustomizations` | Top-level create or update input | When set to `true`, enables cart transforms and other function-based merchandise modifications. |
| `withDeliveryCustomizations` | `deliveryMethod.fetchAvailableDeliveryOptions` | When `true` (the default), runs delivery customization functions while fetching delivery options, so the returned options reflect the merchant's configured customizations. Set to `false` to bypass these functions and return the raw options. |

***

## API migration reference

### Mutation mapping

| Old mutation | New approach |
| - | - |
| [`subscriptionContractCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractCreate) | Use `subscriptionContractCreateCalculate` |
| [`subscriptionContractUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractUpdate) | Use `subscriptionContractUpdateCalculate` |
| [`subscriptionContractAtomicCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractAtomicCreate) | Use `subscriptionContractCreateCalculate` |
| [`subscriptionContractProductChange`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractProductChange) | Use `subscriptionContractUpdateCalculate` |
| [`subscriptionDraftLineAdd`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftLineAdd) | Include in `lines[]` input |
| [`subscriptionDraftLineUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftLineUpdate) | Include updated line with the same `id` in `lines[]` |
| [`subscriptionDraftLineRemove`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftLineRemove) | Omit line from `lines[]` |
| [`subscriptionDraftDiscountAdd`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftDiscountAdd) | Include `orderDiscount` in `manualDiscounts[]` input |
| [`subscriptionDraftDiscountUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftDiscountUpdate) | Include updated `orderDiscount` with the same `id` in `manualDiscounts[]` |
| [`subscriptionDraftDiscountRemove`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftDiscountRemove) | Omit discount from `manualDiscounts[]` |
| [`subscriptionDraftDiscountCodeApply`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftDiscountCodeApply) | Include in `discountCodes[]` input |
| [`subscriptionDraftFreeShippingDiscountAdd`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftFreeShippingDiscountAdd) | Include `deliveryDiscount` in `manualDiscounts[]` |
| [`subscriptionDraftFreeShippingDiscountUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftFreeShippingDiscountUpdate) | Include updated `deliveryDiscount` with the same `id` in `manualDiscounts[]` |
| [`subscriptionDraftUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftUpdate) | Recalculate with additional input |
| [`subscriptionDraftCommit`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftCommit) | Use `subscriptionContractCalculationCommit` |
| [`subscriptionBillingCycleContractEdit`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionBillingCycleContractEdit) | Use `subscriptionBillingCycleContractEditCalculate` |
| [`subscriptionBillingCycleContractDraftConcatenate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionBillingCycleContractDraftConcatenate) | No calculate API equivalent yet; continue using the draft API |
| [`subscriptionBillingCycleContractDraftCommit`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionBillingCycleContractDraftCommit) | Use `subscriptionContractCalculationCommit` |

### Deprecated and renamed fields

The `SubscriptionContractCalculation` API introduces changes to how certain contract attributes are managed. The following fields have been deprecated, renamed, or moved.

#### Contract status

Contract status is now managed using dedicated mutations instead of being set through the draft or contract calculation input. This change decouples contract status from the contract versioning model.

| Old approach | New approach |
| - | - |
| Set `status` field in `SubscriptionDraftInput` during commit. | Use dedicated status mutations: [`subscriptionContractActivate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractActivate), [`subscriptionContractPause`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractPause), [`subscriptionContractCancel`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractCancel), [`subscriptionContractExpire`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractExpire), [`subscriptionContractFail`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractFail). |

#### Line pricing policy

The `pricingPolicy` field on subscription lines has been renamed to `appManagedPricingPolicy`. This name change clarifies that the field contains app-managed pricing data that isn't used during contract calculation. The `SubscriptionContractCalculation` API calculates prices based on the current catalog and any applied discounts.

| Old field | New field |
| - | - |
| `pricingPolicy` | `appManagedPricingPolicy` |

#### Billing configuration

The `nextBillingDate`, `minCycles`, and `maxCycles` fields have been moved into a new `AppManagedBillingConfig` object. This consolidates app-managed billing metadata that isn't used during contract calculation into a single location.

| Old fields | New field |
| - | - |
| `nextBillingDate`, `minCycles`, `maxCycles` | `appManagedBillingConfig.nextBillingDate`, `appManagedBillingConfig.minCycles`, `appManagedBillingConfig.maxCycles` |

#### Multiple fulfillment configuration

**Multi fulfillment is now optional:**

Passing `multiFulfillment` is only required for pre-paid subscriptions that have multiple deliveries per billing period. Omit the multi fulfillment input to use the billing cadence as the delivery cadence.

The `SubscriptionContractCalculation` API introduces explicit control over the number of fulfillments per billing cycle through a new `multiFulfillment` field. Previously, the number of deliveries per billing cycle was implicitly derived from the relationship between billing and delivery policy intervals. The new approach makes this configuration explicit.

The `multiFulfillment` field accepts a `SubscriptionMultipleFulfillmentConfigInput` with the following fields:

| Field | Type | Required | Description |
| - | - | - | - |
| `cadence` | Object | Yes | The cadence for calculating fulfillment dates. |
| `numberOfFulfillments` | Integer | Yes | The number of fulfillments per billing cycle. Must be at least 2. |

### Explore the API

Use the [GraphQL Admin API docs](https://shopify.dev/docs/api/admin-graphql/2026-10) to explore the new API mutations, input types, and return types.

***

## Create a subscription contract

### Old approach (Subscription​Draft)

With the SubscriptionDraft API, creating a contract requires multiple sequential mutations:

1. Create a draft for the new contract using [`subscriptionContractCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractCreate).
2. Add lines to the draft using [`subscriptionDraftLineAdd`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftLineAdd).
3. Commit the draft to create the contract using [`subscriptionDraftCommit`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftCommit).

### New approach (Subscription​Contract​Calculation)

With the `SubscriptionContractCalculation` API, you submit the complete desired state for the new contract in a single mutation. The server calculates pricing, applies taxes, and returns an immutable result snapshot.

1. Submit the new contract's desired state to create a contract calculation:

   ## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

   ## Create contract calculation

   ```graphql
   mutation CreateCalculation {
     subscriptionContractCreateCalculate(
       contractCreateInput: {
         # Control contract calculation behavior
         withMerchandiseCustomizations: true


         # Customer to create the contract for (must belong to the current shop)
         customerId: "gid://shopify/Customer/123"


         # Currency for the contract
         currencyCode: USD


         # Define all lines (at least one required)
         lines: [
           {
             productVariantLine: {
               productVariantId: "gid://shopify/ProductVariant/111"
               quantity: 1
               customAttributes: []
               discounts: []  # Line-scoped discounts; pass [] for none
             }
           }
         ]


         # Define billing policy
         billingPolicy: {
           cadence: {
             unit: MONTH
             count: 1
           }
         }


         # Define delivery policy
         deliveryPolicy: {
           multiFulfillment: {
             cadence: { unit: WEEK, count: 2 }
             numberOfFulfillments: 2
           }
         }


         # Define delivery method (use { none: true } for digital-only subscriptions)
         deliveryMethod: {
           shipping: {
             address: {
               firstName: "Quinn"
               lastName: "Ishida"
               address1: "123 Main St"
               city: "Toronto"
               provinceCode: "ON"
               countryCode: CA
               zip: "M5V 1A1"
             }
             deliveryPrice: {
               amount: "5.00"
               currencyCode: USD
             }
           }
         }


         # Define payment method (use { none: true } for no payment method)
         paymentMethod: {
           customerPaymentMethod: {
             id: "gid://shopify/CustomerPaymentMethod/456"
           }
         }


         # Define discount codes to apply (pass an empty array for none)
         discountCodes: []


         # Define manual discounts (pass an empty array for no manual discounts)
         # Supports two types: orderDiscount, deliveryDiscount
         manualDiscounts: []


         # Define custom attributes (pass an empty array for none)
         customAttributes: []
       }
     ) {
       subscriptionContractCalculation {
         ... on SubscriptionContractCalculationPending {
           id
         }
       }
       userErrors {
         field
         message
         code
       }
     }
   }
   ```

   ## JSON response

   ```json
   {
     "data": {
       "subscriptionContractCreateCalculate": {
         "subscriptionContractCalculation": {
           "id": "gid://shopify/SubscriptionContractCalculation/789"
         },
         "userErrors": []
       }
     }
   }
   ```

2. Poll for the contract calculation result:

   ## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

   ## Poll for result

   ```graphql
   query PollCalculation {
     subscriptionContractCalculation(
       id: "gid://shopify/SubscriptionContractCalculation/789"
     ) {
       __typename
       ... on SubscriptionContractCalculationPending {
         id
       }
       ... on SubscriptionContractCalculationSuccess {
         id
         calculatedContract {
           lines(first: 10) {
             edges {
               node {
                 id
                 variantId
                 quantity
               }
             }
           }
         }
       }
       ... on SubscriptionContractCalculationFailure {
         id
         errors { code }
       }
     }
   }
   ```

   ## JSON response (pending)

   ```json
   {
     "data": {
       "subscriptionContractCalculation": {
         "__typename": "SubscriptionContractCalculationPending",
         "id": "gid://shopify/SubscriptionContractCalculation/789"
       }
     }
   }
   ```

3. Commit the contract calculation to create the contract:

   ## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

   ## Commit contract calculation

   ```graphql
   mutation CommitCalculation {
     subscriptionContractCalculationCommit(
       id: "gid://shopify/SubscriptionContractCalculation/789"
     ) {
       # The return type is a union: SubscriptionContract (create/update)
       # or SubscriptionBillingCycleEditedContract (billing cycle edit).
       contract {
         ... on SubscriptionContract {
           id
           status
         }
       }
       userErrors {
         field
         message
       }
     }
   }
   ```

   ## JSON response

   ```json
   {
     "data": {
       "subscriptionContractCalculationCommit": {
         "contract": {
           "id": "gid://shopify/SubscriptionContract/999",
           "status": "ACTIVE"
         },
         "userErrors": []
       }
     }
   }
   ```

***

## Update a subscription contract

### Old approach (Subscription​Draft)

With the SubscriptionDraft API, updating a contract requires multiple sequential mutations:

1. Create a draft from the existing contract using [`subscriptionContractUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractUpdate).
2. Add, update, or remove lines using [`subscriptionDraftLineAdd`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftLineAdd), [`subscriptionDraftLineUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftLineUpdate), or [`subscriptionDraftLineRemove`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftLineRemove).
3. Apply discounts using [`subscriptionDraftDiscountCodeApply`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftDiscountCodeApply), [`subscriptionDraftDiscountAdd`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftDiscountAdd), or [`subscriptionDraftFreeShippingDiscountAdd`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftFreeShippingDiscountAdd).
4. Commit the draft to apply changes using [`subscriptionDraftCommit`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftCommit).

### New approach (Subscription​Contract​Calculation)

With the `SubscriptionContractCalculation` API, you submit only the fields you want to change in a single mutation. Omitted fields are left unchanged.

Fetch the existing [SubscriptionContract](https://shopify.dev/docs/api/admin-graphql/latest/objects/SubscriptionContract) state using the [subscriptionContract](https://shopify.dev/docs/api/admin-graphql/latest/queries/subscriptionContract) query, then apply any changes before submitting an updated version of the `SubscriptionContract` attributes for contract calculation.

1. Submit the desired state to create a contract calculation. On an update, only `withMerchandiseCustomizations` must be provided; all other fields are optional and omitted fields are left unchanged:

   ## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

   ## Create contract calculation

   ```graphql
   mutation UpdateCalculation {
     subscriptionContractUpdateCalculate(
       contractId: "gid://shopify/SubscriptionContract/123"
       contractUpdateInput: {
         # Control contract calculation behavior
         withMerchandiseCustomizations: true


         # Define all lines (replaces existing lines when provided)
         lines: [
           {
             productVariantLine: {
               # Include id to keep existing line
               id: "gid://shopify/SubscriptionLine/existing-line-uuid"
               productVariantId: "gid://shopify/ProductVariant/111"
               quantity: 1
               customAttributes: []
               discounts: []  # Line-scoped discounts; pass [] for none
             }
           }
           {
             productVariantLine: {
               # Omit id to add new line
               productVariantId: "gid://shopify/ProductVariant/789"
               quantity: 2
               customAttributes: []
               discounts: []
             }
           }
         ]


         # Define discount codes to apply (resolved into manual discounts; not persisted as codes)
         discountCodes: [
           { redeemCode: "SAVE10" }
         ]


         # Define all manual discounts (replaces existing manual discounts)
         # Supports two types: orderDiscount, deliveryDiscount
         manualDiscounts: [
           {
             orderDiscount: {
               # Include id to keep an existing order discount
               id: "gid://shopify/SubscriptionDiscount/existing-discount-uuid"
               title: "10% off subscription"
               value: {
                 percentage: 10
               }
               recurringCycleLimit: 0  # 0 = no limit
             }
           }
           {
             deliveryDiscount: {
               # Omit id for a new delivery discount
               title: "Free shipping for 3 months"
               value: {
                 percentage: 100
               }
               recurringCycleLimit: 3  # Apply for 3 billing cycles
             }
           }
         ]


         # Define billing policy (replaces existing billing policy)
         billingPolicy: {
           anchors: [
             {
               monthday: {
                 dayOfMonth: 7
               }
             }
           ]
           cadence: {
             unit: MONTH
             count: 2
           }
         }


         # Define delivery policy (replaces existing delivery policy)
         deliveryPolicy: {
           anchors: {
             weekday: {
               dayOfWeek: TUESDAY
             }
           }
           multiFulfillment: {
             cadence: { unit: WEEK, count: 1 }
             numberOfFulfillments: 8
           }
         }


         # Define delivery method (replaces existing delivery method when provided)
         deliveryMethod:{
           pickup: {
             title: "Test",
             locationId: "gid://shopify/Location/1234",
             deliveryPrice: {
               amount: "0",
               currencyCode: GBP
             }
           }
         }


         # Define payment method (replaces existing payment method when provided)
         paymentMethod: {
           customerPaymentMethod: {
             id: "gid://shopify/CustomerPaymentMethod/1234"
           }
         }


         # Define note (replaces existing note)
         note: "Test"
       }
     ) {
       subscriptionContractCalculation {
         ... on SubscriptionContractCalculationPending {
           id
         }
       }
       userErrors {
         field
         message
       }
     }
   }
   ```

   ## JSON response

   ```json
   {
     "data": {
       "subscriptionContractUpdateCalculate": {
         "subscriptionContractCalculation": {
           "id": "gid://shopify/SubscriptionContractCalculation/789"
         },
         "userErrors": []
       }
     }
   }
   ```

2. Poll for the contract calculation result:

   ## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

   ## Poll for result

   ```graphql
   query PollCalculation {
     subscriptionContractCalculation(
       id: "gid://shopify/SubscriptionContractCalculation/789"
     ) {
       __typename
       ... on SubscriptionContractCalculationPending {
         id
       }
       ... on SubscriptionContractCalculationSuccess {
         id
         calculatedContract {
           lines(first: 10) {
             edges {
               node {
                 id
                 variantId
                 quantity
               }
             }
           }
         }
         warnings {
           code
           message
         }
         projectedOrderTotals {
           subtotal { amount currencyCode }
           totalDelivery { amount currencyCode }
           totalTax { amount currencyCode }
           totalMerchandiseDiscounts { amount currencyCode }
           totalDeliveryDiscounts { amount currencyCode }
           total { amount currencyCode }
         }
       }
       ... on SubscriptionContractCalculationFailure {
         id
         errors { code }
       }
     }
   }
   ```

   ## JSON response (pending)

   ```json
   {
     "data": {
       "subscriptionContractCalculation": {
         "__typename": "SubscriptionContractCalculationPending",
         "id": "gid://shopify/SubscriptionContractCalculation/789"
       }
     }
   }
   ```

3. Commit the contract calculation to apply changes:

   ## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

   ## Commit contract calculation

   ```graphql
   mutation CommitCalculation {
     subscriptionContractCalculationCommit(
       id: "gid://shopify/SubscriptionContractCalculation/789"
     ) {
       # The return type is a union: SubscriptionContract (create/update)
       # or SubscriptionBillingCycleEditedContract (billing cycle edit).
       contract {
         ... on SubscriptionContract {
           id
           status
         }
       }
       userErrors {
         field
         message
       }
     }
   }
   ```

   ## JSON response

   ```json
   {
     "data": {
       "subscriptionContractCalculationCommit": {
         "contract": {
           "id": "gid://shopify/SubscriptionContract/123",
           "status": "ACTIVE"
         },
         "userErrors": []
       }
     }
   }
   ```

***

## Edit a single billing cycle

Apply a one-time change to a single billing cycle of a subscription without changing the recurring contract. Later cycles continue to bill from the underlying contract. A billing cycle can contain more than one delivery (for example, prepaid or multi-fulfillment subscriptions), and the edit applies to the whole cycle.

### Old approach (Subscription​Draft)

With the [`SubscriptionDraft`](https://shopify.dev/docs/api/admin-graphql/latest/objects/SubscriptionDraft) object, editing one billing cycle requires multiple sequential mutations:

1. Create a draft scoped to the target cycle using [`subscriptionBillingCycleContractEdit`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionBillingCycleContractEdit).
2. Add, update, or remove lines and discounts on the draft using the `subscriptionDraft*` mutations.
3. Commit the draft using [`subscriptionBillingCycleContractDraftCommit`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionBillingCycleContractDraftCommit).

### New approach (Subscription​Contract​Calculation)

With the `SubscriptionContractCalculation` API, you submit the complete desired state for the cycle in a single mutation and identify the cycle with a selector, then poll and commit exactly as you do for a contract update.

1. Submit the desired state for the target cycle to create a contract calculation, identifying the cycle with a [`billingCycleSelector`](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/SubscriptionBillingCycleSelector). Select the cycle either:

   1. By its `index`:

      ```graphql
      mutation {
        subscriptionBillingCycleContractEditCalculate(
          contractId: "gid://shopify/SubscriptionContract/1"
          billingCycleSelector: { index: 2 }
          billingCycleEditInput: {
            withMerchandiseCustomizations: true,
            # The complete desired state for this cycle (lines, discounts, delivery, and so on).
            lines: [
              {
                productVariantLine: {
                  productVariantId: "gid://shopify/ProductVariant/1"
                  quantity: 2
                  customAttributes: []
                  discounts: []  # Line-scoped discounts; pass [] for none
                }
              }
            ]
          }
        ) {
          subscriptionContractCalculation {
            ... on SubscriptionContractCalculationPending {
              id
            }
          }
          userErrors {
            field
            message
          }
        }
      }
      ```

   2. Or by a `date` that falls within the cycle:

      ```graphql
      billingCycleSelector: { date: "2025-06-01T00:00:00Z" }
      ```

2. Poll the calculation and commit it as described in [Update a subscription contract](#update-a-subscription-contract). You wait for the calculation to succeed, then commit it with `subscriptionContractCalculationCommit`.

Committing creates and commits a new contract version scoped to that single billing cycle, leaving the recurring contract unchanged.

***

## Manage discounts

The `SubscriptionContractCalculation` API splits discounts into two separate input fields that replace the multiple draft-based discount mutations:

* **`discountCodes[]`**: Discount codes to apply during the calculation. Applied codes are resolved into manual discounts on the resulting contract; codes aren't persisted as codes, so there's nothing to preserve or replace across calculations. Defaults to an empty array.
* **`manualDiscounts[]`**: Manual order and delivery discounts. This is a `@oneOf` input — each entry is either an `orderDiscount` or a `deliveryDiscount`.

For line-scoped discounts (discounts that apply to a single line), use the `discounts[]` field on each line input. See [Line-scoped discounts](#line-scoped-discounts).

**Manual discounts replacement behavior:**

The `manualDiscounts` array replaces **all** existing manual discounts on the contract. To keep an existing discount, include it in the array with its `id`. To remove a discount, omit it from the array. To add a new discount, include it without an `id`. To remove all manual discounts, pass an empty array (`[]`).

### Discount types

| Discount type | Old mutation(s) | New input field | Description |
| - | - | - | - |
| Code discount | `subscriptionDraftDiscountCodeApply` | `discountCodes[]` | Apply a discount code by its redeem code. |
| Order discount | `subscriptionDraftDiscountAdd`, `subscriptionDraftDiscountUpdate`, `subscriptionDraftDiscountRemove` | `manualDiscounts[].orderDiscount` | Apply a fixed or percentage discount to all lines. |
| Delivery discount | `subscriptionDraftFreeShippingDiscountAdd`, `subscriptionDraftFreeShippingDiscountUpdate` | `manualDiscounts[].deliveryDiscount` | Apply a discount to shipping or delivery charges. |
| Line-scoped discount | `subscriptionDraftDiscountAdd` (line-scoped) | `lines[].productVariantLine.discounts[]` | Apply a fixed or percentage discount to a single line. |

### Apply a discount code

To apply a discount code to an existing contract, include an entry in the `discountCodes` array:

## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

## Apply code discount

```graphql
mutation ApplyCodeDiscount {
  subscriptionContractUpdateCalculate(
    contractId: "gid://shopify/SubscriptionContract/123"
    contractUpdateInput: {
      discountCodes: [
        { redeemCode: "SAVE10" }
      ]
    }
  ) {
    subscriptionContractCalculation {
      ... on SubscriptionContractCalculationPending {
        id
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

### Apply an order discount

Order discounts apply to all lines on the contract. They support percentage or fixed amount values:

## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

## Percentage order discount

```graphql
mutation ApplyOrderDiscount {
  subscriptionContractUpdateCalculate(
    contractId: "gid://shopify/SubscriptionContract/123"
    contractUpdateInput: {
      manualDiscounts: [
        {
          orderDiscount: {
            title: "10% loyalty discount"
            value: {
              percentage: 10
            }
            recurringCycleLimit: 0  # 0 = applies indefinitely
          }
        }
      ]
    }
  ) {
    subscriptionContractCalculation {
      ... on SubscriptionContractCalculationPending {
        id
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

## Fixed amount order discount

```graphql
mutation ApplyFixedOrderDiscount {
  subscriptionContractUpdateCalculate(
    contractId: "gid://shopify/SubscriptionContract/123"
    contractUpdateInput: {
      manualDiscounts: [
        {
          orderDiscount: {
            title: "$5 off subscription"
            value: {
              fixedAmount: {
                appliesOnEachItem: true
                amount: { amount: "5.00", currencyCode: USD }
              }
            }
            recurringCycleLimit: 3  # Applies for 3 billing cycles
          }
        }
      ]
    }
  ) {
    subscriptionContractCalculation {
      ... on SubscriptionContractCalculationPending {
        id
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

### Apply a delivery discount

Delivery discounts apply to shipping or delivery charges. For example, to offer free shipping:

## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

## Free shipping discount

```graphql
mutation ApplyDeliveryDiscount {
  subscriptionContractUpdateCalculate(
    contractId: "gid://shopify/SubscriptionContract/123"
    contractUpdateInput: {
      manualDiscounts: [
        {
          deliveryDiscount: {
            title: "Free shipping"
            value: {
              percentage: 100
            }
            recurringCycleLimit: 0  # 0 = free shipping indefinitely
          }
        }
      ]
    }
  ) {
    subscriptionContractCalculation {
      ... on SubscriptionContractCalculationPending {
        id
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

### Combine multiple discounts

You can apply multiple discounts of different types in a single calculation. Include discount codes in `discountCodes[]` and manual discounts in `manualDiscounts[]`:

## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

## Multiple discount types

```graphql
mutation ApplyMultipleDiscounts {
  subscriptionContractUpdateCalculate(
    contractId: "gid://shopify/SubscriptionContract/123"
    contractUpdateInput: {
      discountCodes: [
        { redeemCode: "SAVE10" }
      ]
      manualDiscounts: [
        {
          orderDiscount: {
            title: "Loyalty reward"
            value: { percentage: 5 }
            recurringCycleLimit: 0
          }
        }
        {
          deliveryDiscount: {
            title: "Free shipping promo"
            value: { percentage: 100 }
            recurringCycleLimit: 6
          }
        }
      ]
    }
  ) {
    subscriptionContractCalculation {
      ... on SubscriptionContractCalculationPending {
        id
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

### Line-scoped discounts

To apply a discount to a single line, include it in the `discounts[]` field on that line's input. Each line-scoped discount takes `title`, `value`, and `recurringCycleLimit` fields, and optionally an `id` to update an existing line discount:

## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

## Line-scoped discount

```graphql
mutation ApplyLineDiscount {
  subscriptionContractUpdateCalculate(
    contractId: "gid://shopify/SubscriptionContract/123"
    contractUpdateInput: {
      lines: [
        {
          productVariantLine: {
            id: "gid://shopify/SubscriptionLine/line-uuid-1"
            productVariantId: "gid://shopify/ProductVariant/111"
            quantity: 1
            customAttributes: []
            discounts: [
              {
                title: "10% off this line"
                value: { percentage: 10 }
                recurringCycleLimit: 0
              }
            ]
          }
        }
      ]
    }
  ) {
    subscriptionContractCalculation {
      ... on SubscriptionContractCalculationPending {
        id
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

### Remove all discounts

To remove all manual discounts from a contract, pass an empty `manualDiscounts` array and an empty `discountCodes` array:

## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

## Remove all discounts

```graphql
mutation RemoveAllDiscounts {
  subscriptionContractUpdateCalculate(
    contractId: "gid://shopify/SubscriptionContract/123"
    contractUpdateInput: {
      manualDiscounts: []
      discountCodes: []
    }
  ) {
    subscriptionContractCalculation {
      ... on SubscriptionContractCalculationPending {
        id
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

***

## Fetch delivery options

The `deliveryOptions` field on `SubscriptionContractCalculationSuccess` returns the available delivery options that the calculation computed. This field replaces the [`SubscriptionDraft.deliveryOptions`](https://shopify.dev/docs/api/admin-graphql/latest/objects/SubscriptionDraft#field-SubscriptionDraft.fields.deliveryOptions) field from the `SubscriptionDraft` API, and returns all available options.

The `SubscriptionContractCalculationSuccess` type also exposes:

* `warnings`: Non-fatal warnings produced during the calculation. The calculation still succeeded; warnings inform the merchant about issues that should be reviewed before committing.
* `projectedOrderTotals`: Projected order totals (subtotal, total delivery, estimated tax, merchandise discounts, delivery discounts, and grand total) for the calculated contract. Null when the calculation only discovered delivery options for an address rather than calculating committed totals.

Each option is a `SubscriptionContractCalculationDeliveryOption`, which resolves to one of the following types:

* `SubscriptionContractCalculationShippingOption`
* `SubscriptionContractCalculationLocalDeliveryOption`
* `SubscriptionContractCalculationPickupOption`

Fetching delivery options is opt-in. A calculation that sets or keeps a committed delivery method uses a faster path that doesn't look up the full set of rates, so it doesn't return the complete set of options. To fetch all available options for an address, provide `fetchAvailableDeliveryOptions` in the `deliveryMethod` input instead of a method. This fetches the options but leaves the contract's committed delivery method unchanged:

* On a create, the calculation commits no method.
* On an update, the calculation inherits the existing method.

**Note:**

`deliveryMethod` is a [`@oneOf` input](https://spec.graphql.org/draft/#sec--oneOf). Provide exactly one of `shipping`, `localDelivery`, `pickup`, `none`, or `fetchAvailableDeliveryOptions`. Providing a committed method and `fetchAvailableDeliveryOptions` in the same calculation is rejected.

### Old approach (Subscription​Draft)

With the SubscriptionDraft API, fetching and setting a delivery option requires multiple sequential mutations and a separate asynchronous query:

1. Create a draft using [`subscriptionContractUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractUpdate) (or [`subscriptionContractCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionContractCreate)).
2. Query the [`deliveryOptions`](https://shopify.dev/docs/api/admin-graphql/latest/objects/SubscriptionDraft#field-SubscriptionDraft.fields.deliveryOptions) field on the [SubscriptionDraft](https://shopify.dev/docs/api/admin-graphql/latest/objects/SubscriptionDraft) with a `deliveryAddress`, polling until it returns a non-null result. Delivery option lookup is asynchronous and returns `null` while pending.
3. Set the selected method using [`subscriptionDraftUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftUpdate) with a `deliveryMethod`.
4. Commit the draft using [`subscriptionDraftCommit`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/subscriptionDraftCommit).

### New approach (Subscription​Contract​Calculation)

With the `SubscriptionContractCalculation` API, you fetch delivery options with a calculation, read them off the result, then submit a second calculation that commits the selected method.

1. Submit a contract calculation that fetches the delivery options by providing `fetchAvailableDeliveryOptions` in the `deliveryMethod` input:

   ## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

   ## Fetch delivery options

   ```graphql
   mutation FetchDeliveryOptions {
     subscriptionContractUpdateCalculate(
       contractId: "gid://shopify/SubscriptionContract/123"
       contractUpdateInput: {
         withMerchandiseCustomizations: true


         # Fetch delivery options for this address without committing a method
         deliveryMethod: {
           fetchAvailableDeliveryOptions: {
             # Run delivery customization functions while discovering options (default)
             withDeliveryCustomizations: true


             address: {
               firstName: "Quinn"
               lastName: "Ishida"
               address1: "123 Main St"
               city: "Toronto"
               provinceCode: "ON"
               countryCode: CA
               zip: "M5V 1A1"
             }
           }
         }
       }
     ) {
       subscriptionContractCalculation {
         ... on SubscriptionContractCalculationPending {
           id
         }
       }
       userErrors {
         field
         message
       }
     }
   }
   ```

   ## JSON response

   ```json
   {
     "data": {
       "subscriptionContractUpdateCalculate": {
         "subscriptionContractCalculation": {
           "id": "gid://shopify/SubscriptionContractCalculation/789"
         },
         "userErrors": []
       }
     }
   }
   ```

2. Poll for the contract calculation result (see the [recommended polling strategy](#polling-pattern)) and read the `deliveryOptions`. Each option type is part of a union, so use inline fragments to select its fields:

   ## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

   ## Read delivery options

   ```graphql
   query PollDeliveryOptions {
     subscriptionContractCalculation(
       id: "gid://shopify/SubscriptionContractCalculation/789"
     ) {
       __typename
       ... on SubscriptionContractCalculationPending {
         id
       }
       ... on SubscriptionContractCalculationSuccess {
         id
         deliveryOptions {
           __typename
           ... on SubscriptionContractCalculationShippingOption {
             title
             code
             price { amount currencyCode }
           }
           ... on SubscriptionContractCalculationLocalDeliveryOption {
             title
             code
             phoneRequired
             price { amount currencyCode }
           }
           ... on SubscriptionContractCalculationPickupOption {
             title
             code
             pickupTime
             price { amount currencyCode }
             location { id name }
           }
         }
       }
       ... on SubscriptionContractCalculationFailure {
         id
         errors { code }
       }
     }
   }
   ```

   ## JSON response (success)

   ```json
   {
     "data": {
       "subscriptionContractCalculation": {
         "__typename": "SubscriptionContractCalculationSuccess",
         "id": "gid://shopify/SubscriptionContractCalculation/789",
         "deliveryOptions": [
           {
             "__typename": "SubscriptionContractCalculationShippingOption",
             "title": "Standard",
             "code": "Standard",
             "price": { "amount": "5.00", "currencyCode": "CAD" }
           },
           {
             "__typename": "SubscriptionContractCalculationShippingOption",
             "title": "Express",
             "code": "Express",
             "price": { "amount": "15.00", "currencyCode": "CAD" }
           }
         ]
       }
     }
   }
   ```

3. Submit a second contract calculation that commits the selected option as the `deliveryMethod`. Map the chosen option's `title` and `code` directly, and map its `price` to the method's `deliveryPrice` field:

   ## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

   ## Select a delivery option

   ```graphql
   mutation SelectDeliveryOption {
     subscriptionContractUpdateCalculate(
       contractId: "gid://shopify/SubscriptionContract/123"
       contractUpdateInput: {
         withMerchandiseCustomizations: true


         # Commit the option chosen from deliveryOptions
         deliveryMethod: {
           shipping: {
             address: {
               firstName: "Quinn"
               lastName: "Ishida"
               address1: "123 Main St"
               city: "Toronto"
               provinceCode: "ON"
               countryCode: CA
               zip: "M5V 1A1"
             }
             title: "Standard"
             code: "Standard"
             deliveryPrice: {
               amount: "5.00"
               currencyCode: CAD
             }
           }
         }
       }
     ) {
       subscriptionContractCalculation {
         ... on SubscriptionContractCalculationPending {
           id
         }
       }
       userErrors {
         field
         message
       }
     }
   }
   ```

4. Poll for the second contract calculation result, then commit it with `subscriptionContractCalculationCommit` to apply the selected delivery method to the contract. This follows the same poll-then-commit pattern as the create and update flows above.

### Delivery customization functions

When a calculation fetches delivery options, the `withDeliveryCustomizations` field on `fetchAvailableDeliveryOptions` controls whether [delivery customization](https://shopify.dev/docs/api/functions/latest/delivery-customization) functions run:

* `true` (the default): Functions run, so the returned `deliveryOptions` reflect any options the merchant's customizations hide, rename, or re-order.
* `false`: Functions are bypassed, and the raw delivery options are returned.

The `SubscriptionDraft` API doesn't run delivery customization functions when computing `deliveryOptions`. For shops with active delivery customizations, the set of options returned by the new API can therefore differ from the old field.

**Note:**

`withDeliveryCustomizations` applies only to calculations that include `fetchAvailableDeliveryOptions`. Calculations that set a committed delivery method and recurring billing attempts always bypass delivery customization functions, because the contract's committed delivery method is fixed and re-running functions can remove it.

***

## Input types reference

**Exploring input types:**

[Explore the API](#explore-the-api) to understand the full input schema, starting from the top-level input types.

### Top-level input types

| Input type | Description |
| - | - |
| `SubscriptionContractCalculationContractCreateInput` | Inputs for creating a new subscription contract. |
| `SubscriptionContractCalculationContractUpdateInput` | Input for updating an existing subscription contract. |
| `SubscriptionContractCalculationBillingCycleEditInput` | Input for editing a single billing cycle of an existing contract. |

### Union input types

**Note:**

The inputs for `lines`, `manualDiscounts`, and `deliveryMethod` fields use the GraphQL [`@oneOf` directive](https://spec.graphql.org/draft/#sec--oneOf). You must provide exactly one of the available input options for each entry. `discountCodes` is a separate non-union array. Refer to the following sections for the specific options available for each field.

#### `SubscriptionContractCalculationLineInput`

Lines use a `@oneOf` input pattern. Provide exactly one of the following options:

* `productVariantLine`: For product variant lines.
* `customLine`: For custom lines without a variant.
* `productVariantParentLine`: For product variant bundle parent lines (available when bundle support is enabled).

**Lines replacement behavior:**

The `lines` array replaces all existing lines. Include all lines that you want to keep and omit any that you want to remove. Use line IDs to identify existing lines for updates.

#### `SubscriptionContractCalculationProductVariantLineInput`

Product variant lines accept the following fields:

| Field | Type | Required | Description |
| - | - | - | - |
| `id` | `ID` | No | The ID of an existing line to update. Omit for new lines. |
| `productVariantId` | `ID` | Yes | The ID of the product variant for this line. |
| `quantity` | `Integer` | Yes | The quantity of the product variant. Must be at least 1. |
| `priceOverride` | [`MoneyInput`](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/MoneyInput) | No | Override price for this line item. |
| `customAttributes` | `[AttributeInput]` | Yes (default `[]`) | Custom attributes for this subscription line. |
| `appManagedPricingPolicy` | `SubscriptionContractCalculationAppManagedPricingPolicyInput` | No | App-managed pricing policy metadata for this line. |
| `originSellingPlanId` | `ID` | No | The ID of the selling plan this line was originally created with. Used to find the delivery profile. |
| `sellingPlanName` | `String` | No | The selling plan name for this line. Defaults to the origin selling plan's current name. |
| `discounts` | `[SubscriptionContractCalculationLineDiscountInput]` | Yes | Line-scoped manual discounts. Pass `[]` for none. |

#### `SubscriptionContractCalculationManualDiscountInput`

Manual discounts use a `@oneOf` input pattern. Provide exactly one of the following options:

* `orderDiscount`: For order discounts that apply to all lines on the contract. Takes `title`, `value`, and `recurringCycleLimit` fields. Optionally takes an `id` to update an existing discount.
* `deliveryDiscount`: For delivery or shipping discounts. Takes `title`, `value`, and `recurringCycleLimit` fields. Optionally takes an `id` to update an existing discount.

**Manual discounts replacement behavior:**

The `manualDiscounts` array replaces all existing manual discounts. Include all discounts that you want to keep and omit any that you want to remove. Use discount IDs to identify existing discounts for updates.

#### `SubscriptionContractCalculationDiscountCodeInput`

Discount codes are provided in the separate `discountCodes[]` array (not part of `manualDiscounts`). Each entry takes:

* `redeemCode`: The discount code string to apply.

Applied codes are resolved into manual discounts on the resulting contract; codes aren't persisted as codes, so there's nothing to preserve or replace across calculations.

#### `SubscriptionContractCalculationDiscountValueInput`

Discount values use a `@oneOf` input pattern. Provide exactly one of the following options:

* `percentage`: An integer percentage value (0–100).
* `fixedAmount`: A fixed money amount with `appliesOnEachItem` (boolean) and `amount` ([`MoneyInput`](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/MoneyInput)).

#### `SubscriptionContractCalculationDeliveryMethodInput`

Delivery methods use a `@oneOf` input pattern. Provide exactly one of the following options:

* `shipping`: For shipping deliveries.
* `localDelivery`: For local delivery.
* `pickup`: For pickup.
* `none`: Explicitly set no delivery method (digital-only subscriptions). Must be `true`.
* `fetchAvailableDeliveryOptions`: To fetch the available delivery options for an address without committing a delivery method. See [Fetch delivery options](#fetch-delivery-options).

#### `SubscriptionContractCalculationPaymentMethodInput`

Payment methods use a `@oneOf` input pattern. Provide exactly one of the following options:

* `customerPaymentMethod`: A vaulted customer payment method. Takes an `id` field (`ID`) for the customer payment method.
* `none`: Explicitly set no payment method. Must be `true`.

#### `SubscriptionContractCalculationFetchDeliveryOptionsInput`

Use this input under `deliveryMethod.fetchAvailableDeliveryOptions` to fetch available delivery options without setting a delivery method.

* `address`: The delivery address to fetch options for.
* `withDeliveryCustomizations`: Optional Boolean. When `true` (the default), delivery customization functions run while fetching options. When `false`, delivery customization functions are bypassed and the raw options are returned.

***

## Handle asynchronous results

The `SubscriptionContractCalculation` API uses asynchronous processing because it aligns contract editing with all other checkout surfaces across Shopify, including subscription billing attempts, checkout, and draft orders.

Most contract calculations complete in less than one second, but the system needs to account for network latency and errors in third-party services. The asynchronous model handles these situations without exposing transient errors or imposing strict API request timeouts.

You can handle contract calculation results by polling the contract calculation query or [subscribing to webhooks](#webhook-integration) for event-driven processing.

### Contract calculation states

A contract calculation progresses through several states from creation to completion. Understanding these states helps you build integrations that handle all possible outcomes.

| State | Description | Webhook |
| - | - | - |
| **Initiated** | The contract calculation is created and waiting to be processed. | — |
| **Processing** | The contract calculation is running with functions and external services. | — |
| **Succeeded** | The contract calculation is ready for review and commit. | `subscription_contract_calculations/succeed` |
| **Failed** | The contract calculation failed. Errors are available on the result. | `subscription_contract_calculations/fail` |
| **Voided** | The contract calculation wasn't processed due to infrastructure issues. | — |
| **Committed** | The contract calculation has been committed and is now active. | `subscription_contracts/create` or `subscription_contracts/update` |

The `subscriptionContractCalculation` query returns a union with three possible GraphQL types. The internal states map to these types as follows:

| GraphQL type | Internal states |
| - | - |
| `SubscriptionContractCalculationPending` | Initiated, Processing |
| `SubscriptionContractCalculationSuccess` | Succeeded, Committed |
| `SubscriptionContractCalculationFailure` | Failed, Voided |

### Polling pattern

After creating a contract calculation, poll the `subscriptionContractCalculation` query until processing completes.

## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

## GraphQL query

```graphql
query PollCalculation($id: ID!) {
  subscriptionContractCalculation(id: $id) {
    __typename
    ... on SubscriptionContractCalculationPending {
      id
    }
    ... on SubscriptionContractCalculationSuccess {
      id
    }
    ... on SubscriptionContractCalculationFailure {
      id
    }
  }
}
```

### Recommended polling strategy

1. **Initial wait**: Wait 1 second after the mutation before the first poll.
2. **Poll interval**: Poll every 500ms.
3. **Timeout**: Stop polling after 30 seconds, or when the contract calculation result is in a failed state.

### Retry safety

All contract calculation operations are safe to retry:

* **Calculate**: Safe to retry. Creates a new contract calculation each time.
* **Commit**: Safe to retry. If already committed, it returns success.
* **Polling**: Safe to call as many times as needed.

### Webhook integration

[Subscribe to webhooks](https://shopify.dev/docs/apps/build/webhooks/subscribe) for event-driven processing instead of polling.

| Webhook topic | Description |
| - | - |
| `subscription_contract_calculations/succeed` | Fires when a contract calculation succeeds and the contract calculation is ready to commit. |
| `subscription_contract_calculations/fail` | Fires when a contract calculation fails and errors are available on the result. |

## POST https://{shop}.myshopify.com/admin/api/{api\_version}/graphql.json

## Create webhook subscription

```graphql
mutation CreateWebhookSubscription {
  webhookSubscriptionCreate(
    topic: SUBSCRIPTION_CONTRACT_CALCULATIONS_SUCCEED
    webhookSubscription: {
      callbackUrl: "https://example.com/webhooks/calculation-success"
      format: JSON
    }
  ) {
    webhookSubscription {
      id
    }
    userErrors {
      field
      message
    }
  }
}
```

## JSON response

```json
{
  "data": {
    "webhookSubscriptionCreate": {
      "webhookSubscription": {
        "id": "gid://shopify/WebhookSubscription/123456789"
      },
      "userErrors": []
    }
  }
}
```

## Webhook payload

```json
{
  "id": 123,
  "admin_graphql_api_id": "gid://shopify/SubscriptionContractCalculation/123",
  "state": "succeeded"
}
```

***

## Backwards compatibility

The `SubscriptionDraft` API will remain available but will not support the new capabilities of the `SubscriptionContractCalculation` API.

### Cross-API compatibility

**Compatibility in progress:**

Compatibility between APIs is still being evaluated. This may work in one of the following ways:

* Allow both the `SubscriptionDraft` and `SubscriptionContractCalculation` APIs to be used on the same contracts.
* Prevent contracts with changes committed through the `SubscriptionContractCalculation` API from being edited using the `SubscriptionDraft` API.

***
