//native
/**
* Create Fulfillment
* Fulfill one or more fulfillment orders of the same order and location (mark items as shipped). Fulfills every remaining item, or only line_items ({ id, quantity } of fulfillment order line items) when given, which needs a single fulfillment order. Optional tracking info; notify_customer sends the shipping confirmation email.
*/
export async function main(
auth: RT.Shopify,
fulfillment_order_ids: string[],
line_items: { id: string; quantity: number }[] | undefined,
tracking_number: string | undefined,
tracking_url: string | undefined,
tracking_company: string | undefined,
notify_customer: boolean | undefined,
message: string | undefined
) {
const foIds = fulfillment_order_ids.map((id) =>
id.startsWith("gid://") ? id : `gid://shopify/FulfillmentOrder/${id}`
)
const lineItems = line_items?.length
? line_items.map((li) => ({
id: li.id.startsWith("gid://")
? li.id
: `gid://shopify/FulfillmentOrderLineItem/${li.id}`,
quantity: li.quantity,
}))
: undefined
if (lineItems && foIds.length > 1) {
throw new Error(
"line_items can only be used with a single fulfillment order"
)
}
const hasTracking = tracking_number || tracking_url || tracking_company
const response = await fetch(
`https://${auth.store_name}.myshopify.com/admin/api/2026-10/graphql.json`,
{
method: "POST",
headers: {
"X-Shopify-Access-Token": auth.token,
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({
query: `mutation ($fulfillment: FulfillmentInput!, $message: String) { fulfillmentCreate(fulfillment: $fulfillment, message: $message) { fulfillment { id legacyResourceId name status displayStatus createdAt updatedAt deliveredAt estimatedDeliveryAt inTransitAt totalQuantity requiresShipping trackingInfo { company number url } location { id name } order { id name } service { handle serviceName } fulfillmentLineItems(first: 250) { nodes { id quantity lineItem { id name sku } } } fulfillmentOrders(first: 10) { nodes { id status } } } userErrors { field message } } }`,
variables: {
fulfillment: {
lineItemsByFulfillmentOrder: foIds.map((fulfillmentOrderId) => ({
fulfillmentOrderId,
fulfillmentOrderLineItems: lineItems,
})),
trackingInfo: hasTracking
? {
number: tracking_number || undefined,
url: tracking_url || undefined,
company: tracking_company || undefined,
}
: undefined,
notifyCustomer: notify_customer || undefined,
},
message: message || undefined,
},
}),
}
)
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
const { data, errors } = await response.json()
if (errors) {
throw new Error(JSON.stringify(errors))
}
if (data.fulfillmentCreate.userErrors.length) {
throw new Error(JSON.stringify(data.fulfillmentCreate.userErrors))
}
return data.fulfillmentCreate
}
Submitted by hugo989 3 hours ago