I’m building an integration that creates order fulfillments via the Admin API, and every attempt fails. I’ve ruled out the common causes and need help identifying the reason. When I try to create a fulfillment, I get: “The api_client does not have access to the fulfillment order.” This happens on both REST (POST /fulfillments.json) and GraphQL (fulfillmentCreateV2). When I GET the fulfillment order, supportedActions only contains “hold”. It does NOT include “create_fulfillment”. Fulfillment order state: - status: open - request_status: unsubmitted - fulfillment_holds: empty (not on hold) - assigned location: active, not legacy What I have already checked: - The custom app has every fulfillment scope (read/write fulfillments, plus read/write for assigned, merchant managed, and third party fulfillment orders) - There are no fulfillment services registered on the store (fulfillment_services returns empty) - The assigned location is active and not legacy - The fulfillment order is not on hold - Tested on API versions 2024-07 and 2025-07 The order fulfills fine manually in the Shopify admin. It only fails through the API. Question: why would an open, non-held fulfillment order on a store with no fulfillment services only show “hold” as a supported action, with no “create_fulfillment”? And how do I enable API fulfillment creation for this store?
Hey @Syed_Haider — good debugging, you’ve already ruled out most of the usual suspects.
The behaviour you’re seeing (supportedActions: ["hold"] + api_client does not have access to the fulfillment order on fulfillmentCreateV2) almost always means the fulfillment order is assigned to a fulfillment service location that your app doesn’t own.
Since API version 2024-10, fulfillmentCreate only succeeds against:
- A merchant-managed location, or
- A third-party fulfillment service location owned by the calling app.
If the assigned location is managed by another fulfillment service — even one your app has read scope on — you’ll get exactly the response you’re seeing: hold is offered (anyone with the right scope can place a hold) but create_fulfillment is not (only the owning service can create the fulfillment).
Things to check
The fact that GET /fulfillment_services.json returns empty isn’t conclusive — that endpoint typically only lists services owned by the calling API client. Query the fulfillment order’s assigned location directly:
query {
fulfillmentOrder(id: "gid://shopify/FulfillmentOrder/...") {
id
status
requestStatus
supportedActions { action externalUrl }
assignedLocation {
location {
id
name
isFulfillmentService
fulfillmentService {
id
handle
serviceName
}
}
}
lineItems(first: 10) {
edges { node { id lineItem { id title } } }
}
}
}
If assignedLocation.location.fulfillmentService is non-null, that’s your answer — the order is owned by that service and only it can fulfill. Your options are:
- Move the FO to a merchant-managed location first with
fulfillmentOrderMove, thenfulfillmentCreate. - Or have the merchant fulfill through the owning service.
One other thing worth ruling out: line items that are gift cards, digital, or part of a subscription / deferred-payment flow can also restrict the action set — the line-items detail in the query above will surface that.
Let me know what assignedLocation resolves to and we can take it from there.