Admin GraphQL API / New mutation

shippingLabelPurchase
Buy shipping labels directly from the GraphQL Admin API

A new mutation that lets your app buy Shopify Shipping labels for a given fulfillment order. The purchase runs asynchronously, so you poll the result to track its status.

On this page
  1. What can you actually do now? (understand it in 30 seconds)
  2. How it works: the flow from purchase request to label retrieval
  3. Inputs you pass to the mutation
  4. The three statuses returned asynchronously
  5. Requirements (scopes, permissions, terms)
  6. Implementation flow (3 steps)
  7. 5 key points for developers
  8. 3 use cases you can apply to your business
  9. A one-line summary you can use in proposals

1What can you actually do now?

added to the GraphQL Admin API. shippingLabelPurchase mutation has been
With this, your app can now buy a Shopify Shipping label for a given fulfillment order from your app.

Before: manual work in the admin

Buying labels was basically centered on actions in the Shopify admin. It was hard to build the full "buy a label" process into your app via the API.

From now on: buy labels via the API

shippingLabelPurchase buy a label by passing the fulfillment order, ship date, packaging, weight, notification settings, and more. You can build it into your app's flow.

2How it works: the flow from purchase request to label retrieval

App Build the input Run mutation shippingLabelPurchase Shopify Select a rate → asynchronously Start the label purchase process No preferred rate → use the cheapest Return a Result ShippingLabel PurchaseResult Poll this Status PENDING_PURCHASE PURCHASED → retrieve the label PURCHASE_FAILED →errors
The key is "asynchronous + polling". Rather than returning the label immediately, the mutation returns a ShippingLabelPurchaseResult and your app watches its status to track whether the purchase has completed.
If you don't pass a preferred rate (preferred carrier / service), Shopify picks one from those available The cheapest rateis selected automatically.

3Input passed to the mutation (ShippingLabelPurchaseInput)

Fulfillment order

Which order's shipment the label is purchased for. It must be eligible for purchase.

Ship date and time

When the shipment goes out (shipping date and time).

Package details

Details of the package. Information about the shipment such as box type and dimensions.

kg

Total weight

The total weight of the shipment. It affects rate calculation.

Customer notification preference

The setting for whether to send a shipment notification to the customer (customer notification preference).

Preferred carrier / service Optional

You can specify a preferred carrier or service. If left unspecified, Shopify picks the cheapest rate.

4Three statuses returned asynchronously

Label purchase runs asynchronously,ShippingLabelPurchaseResult so poll the status to track its progress.

PENDING_PURCHASE

Processing

The purchase is still being processed. Keep polling until it completes.

PURCHASED

Purchase succeeded

The label was purchased successfully. The purchased label can be retrieved from shippingLabels you can retrieve it.

PURCHASE_FAILED

Purchase failed

The purchase failed. Details can be checked from errors you can check the details.

5Requirements (scopes, permissions, terms)

Access scope

write_orders An access scope is required.

User permission

The user performing the operation buy_shipping_labels must have this permission.

Agreeing to the terms

Before purchasing a label via the API, the store must have agreed to the Shopify Shipping terms of service.

This changelog does not cover the finer eligibility conditions such as supported countries, supported plans, and rate limits. Before adopting it, verify in a real store whether it is eligible for purchase and whether the terms have been agreed to.

6Implementation flow (3 steps)

1

Build the input and run the mutation

Pass the fulfillment order, ship date and time, package details, weight, and notification setting (and a preferred rate if needed).

2

Poll the Result

ShippingLabelPurchaseResult the status of PENDING_PURCHASE while it is, keep polling.

3

Branch on the result

PURCHASED if it's shippingLabels fetch the label, andPURCHASE_FAILED if it's errors check it and retry / notify.

design the job on the assumption it's asynchronousis the key. Instead of relying on an immediate mutation response, it's more stable to monitor the status transitions (PENDING → PURCHASED / FAILED) with a worker or queue.

75 points engineers should keep in mind

1. Fully asynchronous = polling required

The mutation doesn't return the label directly; it returns ShippingLabelPurchaseResult Implement on the assumption that you poll the status to monitor completion. Don't expect synchronous completion.

cheapestspecified

2. Rate selection: "omit = cheapest"

If you don't pass a preferred carrier / service, Shopify automatically selects the cheapest available rate. Split the design: omit it for cost optimization, specify it explicitly when you have specific carrier requirements.

3. Scopes and "user permissions" are different things

The app's write_orders Beyond the scope, the executing user needs the buy_shipping_labels permission. Factor into your UI/error design that users without sufficient permissions can't make a purchase.

4. Catch failures with errors to handle them

PURCHASE_FAILED when it fails, errors contains the details. To avoid duplicate purchases and billing accidents, always design failure handling and idempotency (re-running against the same order).

5. Check terms agreement as a "prerequisite"

If the store hasn't agreed to the Shopify Shipping terms of service, purchases via the API aren't possible. Check the terms-agreement status during onboarding at adoption time, and prepare a path for stores that haven't agreed (guidance to agree from the admin) so you don't get stuck in operations.

83 use cases you can apply to your business

USE CASE 1

Automating "bulk label purchasing" in shipping operations

Challenge
An EC store that ships large volumes of orders daily is spending a lot of time purchasing labels one by one from the admin.
Solution
Extract the target fulfillment orders and shippingLabelPurchase run as a batch. Adopt the cheapest rate by leaving the preferred rate unspecified, then poll the results to generate labels all at once.
Impact
Drastically reduces the labor for shipping prep. Achieves both shorter shipping lead times and optimized label costs.
Technical notes
Build a queue + worker on an asynchronous basis, andPENDING→PURCHASED/FAILED manage by status. Make it idempotent so only the failed ones are re-enqueued.
OMS
USE CASE 2

Connect your own OMS / WMS directly to label issuance

The problem
Even though orders and inventory are managed in our own OMS, only shipping labels are issued by switching over to the Shopify admin, creating duplicate operations.
The approach
Trigger on the picking-completion event from the OMS to shippingLabelPurchase run it. Pass package format, weight, and ship date/time from the OMS data, and pull the purchased label shippingLabels in.
The impact
Eliminate manual work between systems and centralize shipping information. Customer notification settings can also be controlled on the API side.
Technical notes
The executing user needs the buy_shipping_labels permission, and the app needs the write_orders scope. Check the target store's terms-acceptance status before rolling out.
USE CASE 3

Visualizing shipping costs and lowest-cost routing

The problem
There's no visibility into which carrier and service incurs how much shipping cost, leaving no levers for cost optimization.
The approach
As a rule, purchase without specifying a preferred rate (i.e., adopt the cheapest), while specifying a preferred carrier only for orders that require it. Accumulate the label/rate information from purchase results to analyze shipping costs.
The impact
You can continuously collect actual shipping-cost figures, providing data to back up carrier negotiations and shipping-fee settings. Cut costs by adopting the cheapest option.
Technical notes
Leverage the spec where behavior changes depending on whether a preferred rate is provided, and design it to branch between "cheapest or specified" based on rules (region, weight, SLA).

9A one-line summary you can use in pitches

"With GraphQL Admin API's shippingLabelPurchase , you can automate shipping-label purchases from your app.
It assumes async + polling, auto-selects the cheapest by omitting the preferred rate, and requireswrite_orders+buy_shipping_labels+ terms acceptance.
A move to connect directly with shipping operations and your own OMS, eliminating the duplicate work of issuing labels."