Hi everyone,
I’m building a Laravel app that integrates with the Shopify Admin API for a dev store:
-
Store:
shopiify-dev-store.myshopify.com -
App is installed with the following scopes (from
granted_scopeslog):
json
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[
“write_products”,
“read_products”,
“write_orders”,
“read_orders”,
“write_fulfillments”,
“read_fulfillments”,
“write_assigned_fulfillment_orders”,
“read_assigned_fulfillment_orders”,
“write_shipping”,
“read_shipping”,
“write_draft_orders”,
“read_draft_orders”,
“write_inventory”,
“read_inventory”,
“write_locations”,
“read_locations”,
“write_themes”,
“read_themes”,
“write_price_rules”,
“read_price_rules”,
“write_discounts”,
“read_discounts”,
“write_checkouts”,
“read_checkouts”,
“write_marketing_events”,
“read_marketing_events”,
“write_resource_feedbacks”,
“read_resource_feedbacks”,
“read_analytics”,
“read_shopify_payments_payouts”
]
So the app has write_fulfillments, read_fulfillments, write_assigned_fulfillment_orders, and read_assigned_fulfillment_orders.
Problem 1: Cannot create a fulfillment for an unfulfilled order
I have an order like this (simplified):
json
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
“id”: 6870850764975,
“admin_graphql_api_id”: “gid://shopify/Order/6870850764975”,
“financial_status”: “paid”,
“fulfillment_status”: null,
“line_items”: [
{
“id”: 15746809725103,
“quantity”: 1,
“requires_shipping”: true,
“fulfillment_service”: “manual”
}
],
“fulfillments”:
}
I tried using the legacy REST endpoint to create a fulfillment:
php
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$payload = [
'fulfillment' => \[
'message' => 'Order #1136 shipped',
'notify_customer' => true,
'tracking_info' => \[
'company' => 'FedEx',
'number' => '102096900',
'url' => 'https://FedEx.com/102096900',
\],
'line_items' => \[
\[
'id' => 15746809725103,
'quantity' => 1,
\],
\],
\],
];
$response = $shop->api()->rest(
'POST',
'/admin/api/2024-10/orders/6870850764975/fulfillments.json',
$payload
);
But this always returns:
- HTTP status: 406 Not Acceptable
The exception is:
text
Copy
1
2
Client error: `POST https://shopiify-dev-store.myshopify.com/admin/api/2024-10/orders/6870850764975/fulfillments.json`
resulted in a `406 Not Acceptable` response
So it looks like the store is on the new fulfillment orders workflow and the old line_items API is not allowed.
Then I tried the new fulfillment orders REST endpoint:
php
Copy
1
2
3
4
5
6
7
8
9
$foResponse = $shop->api()->rest(
'GET',
"/admin/api/2025-10/orders/6870850764975/fulfillment_orders.json"
);
Log::info(‘FULFILLMENT_ORDERS RAW’, [
'status' => $foResponse\['status'\],
'body' => $foResponse\['body'\],
]);
Response:
json
Copy
1
2
3
{
“fulfillment_orders”:
}
So there are no FulfillmentOrder objects for this order, even though:
-
The order is paid
-
It has a shipping address
-
It has a shippable line item (
requires_shipping: true) -
It is unfulfilled
Because fulfillment_orders is empty, I also cannot use:
http
Copy
1
POST /admin/api/2025-10/fulfillments.json
with line_items_by_fulfillment_order, since I have no fulfillment_order_id or fulfillment_order_line_item_id.
So from the REST side:
-
Legacy endpoint → 406
-
New fulfillment_orders endpoint → empty array
Which means there’s currently no way for my app to fulfill this order via API.
Problem 2: Cannot update tracking for an existing fulfillment
I have another order which is already fulfilled (fulfilled from the Admin):
json
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
“id”: 6875231518895,
“order_number”: 1139,
“fulfillment_status”: “fulfilled”,
“fulfillments”: [
{
“id”: 6324579893423,
“status”: “success”,
“tracking_company”: null,
“tracking_number”: null,
“line_items”: [
{
“id”: 15755415584943,
“quantity”: 1,
“fulfillment_status”: “fulfilled”
}
]
}
]
}
I tried to update the tracking info using the REST helper:
php
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$trackingPayload = [
'fulfillment' => \[
'tracking_info' => \[
'number' => '63777665870001',
'company' => 'UPS',
\],
'notify_customer' => true,
\],
];
$updateResponse = $shop->api()->rest(
'POST',
'/admin/api/2024-01/fulfillments/6324579893423/update_tracking.json',
$trackingPayload
);
This returns:
-
HTTP status: 422
-
Body:
"Tracking information update failed."
Then I tried the general update endpoint:
php
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$payload = [
'fulfillment' => \[
'tracking_number' => '63777665870001',
'tracking_company' => 'UPS',
'tracking_url' => 'https://www.ups.com/track?loc=en_US&tracknum=63777665870001',
'notify_customer' => true,
\],
];
$updateResponse = $shop->api()->rest(
'PUT',
'/admin/api/2024-01/fulfillments/6324579893423.json',
$payload
);
But this also returns:
- HTTP status: 406 Not Acceptable
So even for an existing fulfillment, the legacy REST Fulfillment endpoints are not usable on this store (406).
What I’ve already verified
-
The app has all relevant scopes, including:
-
write_fulfillments -
read_fulfillments -
write_assigned_fulfillment_orders -
read_assigned_fulfillment_orders -
write_orders -
read_orders -
etc.
-
-
The order
6870850764975is:-
financial_status: "paid" -
fulfillment_status: null -
Has a normal shipping address
-
A single line item
requires_shipping: true,fulfillment_service: "manual".
-
-
There are no existing fulfillments or refunds on that order.
My questions
-
Why is
GET /admin/api/{version}/orders/{order_id}/fulfillment_orders.jsonreturning an emptyfulfillment_ordersarray for this valid, unfulfilled, paid order?Is there any store setting, fulfillment app, or test‑store limitation that would prevent FulfillmentOrder objects from being created or exposed for this order?
-
Is it expected that all legacy Fulfillment REST endpoints return 406 on a store that uses the fulfillment orders workflow?
-
POST /orders/{id}/fulfillments.json→ 406 -
PUT /fulfillments/{id}.json→ 406
If yes, is the only supported way to create fulfillments and update tracking now via the Admin GraphQL API (e.g.,
fulfillmentCreateV2)? -
-
What is the officially recommended approach to:
-
Fulfill an unfulfilled order from an app on a store like this?
-
Update tracking on an existing fulfillment?
-
I’m happy to switch to GraphQL for fulfillment if that’s the only supported way, but right now I’m blocked because:
-
REST legacy Fulfillment endpoints are rejected (406), and
-
REST FulfillmentOrder endpoint returns an empty list for this particular order.
Any clarification from Shopify staff or anyone who has dealt with this migration before would be really appreciated.
Thanks!