Open fulfillment order's supported_actions only contains "hold" — create_fulfillment missing, api_client access error

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:

  1. A merchant-managed location, or
  2. 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, then fulfillmentCreate.
  • 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.