A space to discuss GraphQL queries, mutations, troubleshooting, throttling, and best practices.
Hello Shopify Community,
I'm encountering an issue while trying to create a draft order with Custom Prices using the GraphQL API. Despite following the documentation, I'm relentlessly running into an issue that I don't understand why it’s happening.
Here is the most relevant part of terminal response:
00:29:23 │ remix │ Line items: [ 00:29:23 │ remix │ { 00:29:23 │ remix │ "variantId": "gid://shopify/ProductVariant/49595202273618", 00:29:23 │ remix │ "quantity": 1, 00:29:23 │ remix │ "originalUnitPrice": { 00:29:23 │ remix │ "amount": "3.50", 00:29:23 │ remix │ "currencyCode": "GBP" 00:29:23 │ remix │ } 00:29:23 │ remix │ }, 00:29:23 │ remix │ { 00:29:23 │ remix │ "variantId": "gid://shopify/ProductVariant/49595202404690", 00:29:23 │ remix │ "quantity": 1, 00:29:23 │ remix │ "originalUnitPrice": { 00:29:23 │ remix │ "amount": "8.00", 00:29:23 │ remix │ "currencyCode": "GBP" 00:29:23 │ remix │ } 00:29:23 │ remix │ } 00:29:23 │ remix │ ] 00:29:23 │ remix │ GraphQL Variables: { 00:29:23 │ remix │ "input": { 00:29:23 │ remix │ "lineItems": [ 00:29:23 │ remix │ { 00:29:23 │ remix │ "variantId": "gid://shopify/ProductVariant/49595202273618", 00:29:23 │ remix │ "quantity": 1, 00:29:23 │ remix │ "originalUnitPrice": { 00:29:23 │ remix │ "amount": "3.50", 00:29:23 │ remix │ "currencyCode": "GBP" 00:29:23 │ remix │ } 00:29:23 │ remix │ }, 00:29:23 │ remix │ { 00:29:23 │ remix │ "variantId": "gid://shopify/ProductVariant/49595202404690", 00:29:23 │ remix │ "quantity": 1, 00:29:23 │ remix │ "originalUnitPrice": { 00:29:23 │ remix │ "amount": "8.00", 00:29:23 │ remix │ "currencyCode": "GBP" 00:29:23 │ remix │ } 00:29:23 │ remix │ } 00:29:23 │ remix │ ], 00:29:23 │ remix │ "useCustomerDefaultAddress": true 00:29:23 │ remix │ } 00:29:23 │ remix │ } 00:29:23 │ remix │ Serialized Payload before sending: {"query":"\n mutation createDraftOrder($input: DraftOrderInput!) {\n draftOrderCreate(input: $input) {\n draftOrder {\n id\n invoiceUrl\n }\n userErrors {\n field\n message\n }\n }\n }\n ","variables":{"input":{"lineItems":[{"variantId":"gid://shopify/ProductVariant/49595202273618","quantity":1,"originalUnitPrice":{"amount":"3.50","currencyCode":"GBP"}},{"vari antId":"gid://shopify/ProductVariant/49595202404690","quantity":1,"originalUnitPrice":{"amount":"8.00","currencyCode":"GBP"}}],"useCustomerDefaultAddress":true}}} 00:29:23 │ remix │ Draft Order Response: { 00:29:23 │ remix │ "errors": [ 00:29:23 │ remix │ { 00:29:23 │ remix │ "message": "Variable $input of type DraftOrderInput! was provided invalid value for lineItems.0.originalUnitPrice (invalid money '{\"amount\" => \"3.50\", \"currencyCode\" => \"GBP\"}'), lineItems.1.originalUnitPrice (invalid money '{\"amount\" => \"8.00\", \"currencyCode\" => \"GBP\"}')", 00:29:23 │ remix │ "locations": [ 00:29:23 │ remix │ { 00:29:23 │ remix │ "line": 2, 00:29:23 │ remix │ "column": 33 00:29:23 │ remix │ } 00:29:23 │ remix │ ], 00:29:23 │ remix │ "extensions": { 00:29:23 │ remix │ "value": { 00:29:23 │ remix │ "lineItems": [ 00:29:23 │ remix │ { 00:29:23 │ remix │ "variantId": "gid://shopify/ProductVariant/49595202273618", 00:29:23 │ remix │ "quantity": 1, 00:29:23 │ remix │ "originalUnitPrice": { 00:29:23 │ remix │ "amount": "3.50", 00:29:23 │ remix │ "currencyCode": "GBP" 00:29:23 │ remix │ } 00:29:23 │ remix │ }, 00:29:23 │ remix │ { 00:29:23 │ remix │ "variantId": "gid://shopify/ProductVariant/49595202404690", 00:29:23 │ remix │ "quantity": 1, 00:29:23 │ remix │ "originalUnitPrice": { 00:29:23 │ remix │ "amount": "8.00", 00:29:23 │ remix │ "currencyCode": "GBP" 00:29:23 │ remix │ } 00:29:23 │ remix │ } 00:29:23 │ remix │ ], 00:29:23 │ remix │ "useCustomerDefaultAddress": true 00:29:23 │ remix │ }, 00:29:23 │ remix │ "problems": [ 00:29:23 │ remix │ { 00:29:23 │ remix │ "path": [ 00:29:23 │ remix │ "lineItems", 00:29:23 │ remix │ 0, 00:29:23 │ remix │ "originalUnitPrice" 00:29:23 │ remix │ ], 00:29:23 │ remix │ "explanation": "invalid money '{\"amount\" => \"3.50\", \"currencyCode\" => \"GBP\"}'", 00:29:23 │ remix │ "message": "invalid money '{\"amount\" => \"3.50\", \"currencyCode\" => \"GBP\"}'" 00:29:23 │ remix │ }, 00:29:23 │ remix │ { 00:29:23 │ remix │ "path": [ 00:29:23 │ remix │ "lineItems", 00:29:23 │ remix │ 1, 00:29:23 │ remix │ "originalUnitPrice" 00:29:23 │ remix │ ], 00:29:23 │ remix │ "explanation": "invalid money '{\"amount\" => \"8.00\", \"currencyCode\" => \"GBP\"}'", 00:29:23 │ remix │ "message": "invalid money '{\"amount\" => \"8.00\", \"currencyCode\" => \"GBP\"}'" 00:29:23 │ remix │ } 00:29:23 │ remix │ ] 00:29:23 │ remix │ } 00:29:23 │ remix │ } 00:29:23 │ remix │ ] 00:29:23 │ remix │ }
The issue consistently appears around how my originalUnitPrice is being processed. The error that persists is:
"message": "Variable $input of type DraftOrderInput! was provided invalid value for lineItems.0.originalUnitPrice (invalid money '{\\"amount\\" => \\"3.50\\", \\"currencyCode\\" => \\"GBP\\"}'), lineItems.1.originalUnitPrice (invalid money '{\\"amount\\" => \\"8.00\\", \\"currencyCode\\" => \\"GBP\\"}')"
As you can see, it says that originalUnitPrice is invalid and it clearly points to an issue with how the MoneyInput is being formatted. As far as my understanding goes, it is not being structured in a way that Shopify API expects - a correctly formatted JSON, using colons (:) for key-value pairs. But this error message shows the => format (e.g., "{\"amount\" => 3.5, \"currencyCode\" => \"GBP\"}") despite all my different efforts to serialize the JSON correctly. Clearly, the => notation is the root problem here since the incorrect format is being flagged as invalid. So, it’s something must be wrong with how the input data is being structured and sent to GraphQL API.
I've already tried several different approaches, used fetch, used direct JSON.stringify, and now using axios.
I even tried some extreme approaches such as manually building the JSON payload string instead of relying on JSON.stringify, axios, or fetch, etc. Just to make sure the transformation and structure are exactly as required by Shopify.
I’ve tried to manually serialize the JSON payload to eliminate any hidden transformations.
I was hoping that by manually serialising the JSON payload I'll pitentially eliminate any hidden transformations or even get any insight into what's going to happen if I completely bypass any serialization that might be happening within these!
What's insane is that no matter the method I keep getting again and again the exact same error.
The originalUnitPrice is structured as an object with amount and currencyCode fields. I've double-checked that the prices are valid numbers and the currency code is correct.
The variant IDs are correct and exist in my store.
This is how I have structured my code:
export const action: ActionFunction = async ({ request }) => {
try {
// Authenticating the app proxy request
const { admin, session } = await authenticate.public.appProxy(request);
. . .
// Ensuring the session has an accessToken
. . .
// Extracting the shop domain from the session
. . .
// Some other business logic
// Preparing line items for the draft order
const lineItems = requestData.items.map((item: DraftOrderItem) => ({
variantId: `gid://shopify/ProductVariant/${item.variant_id}`,
quantity: item.quantity,
originalUnitPrice: {
amount: parseFloat(item.price).toFixed(2).toString(), // Ensuring amount is formatted as a string with two decimal places
currencyCode: item.currencyCode || "GBP",
}
}));
console.log('Line items:', JSON.stringify(lineItems, null, 2));
// GraphQL Variables
const variables = {
input: {
email: requestData.customer_email,
lineItems: lineItems,
useCustomerDefaultAddress: true,
}
};
console.log('GraphQL Variables:', JSON.stringify(variables, null, 2));
// GraphQL mutation
const query = `
mutation createDraftOrder($input: DraftOrderInput!) {
draftOrderCreate(input: $input) {
draftOrder {
id
invoiceUrl
}
userErrors {
field
message
}
}
}
`;
// I'm stringifying the payload directly
const payload = JSON.stringify({
query,
variables
});
console.log('Serialized Payload before sending:', payload);
// Sending the request using axios
const response = await axios.post(
`https://${session.shop}/admin/api/2024-07/graphql.json`,
{
query,
variables
},
{
headers: {
'Content-Type': 'application/json',
'X-Shopify-Access-Token': session.accessToken
}
}
);
const draftOrderData = response.data;
console.log('Draft Order Response:', JSON.stringify(draftOrderData, null, 2));
// Checking for user errors in the response
if (draftOrderData.data?.draftOrderCreate?.userErrors?.length > 0) {
console.error('User errors:', draftOrderData.data.draftOrderCreate.userErrors);
return json({ error: draftOrderData.data.draftOrderCreate.userErrors[0].message }, { status: 400 });
}
// Extracting the invoice URL from the response
const invoiceUrl = draftOrderData.data?.draftOrderCreate?.draftOrder?.invoiceUrl;
return json({ checkout_url: invoiceUrl });
} catch (error) {
console.error('Error creating draft order:', error);
return json({ error: 'An error occurred while creating the draft order' }, { status: 500 });
}
};
It would really help to get specific guidance on the expected format and anything really that points to the correct way to structure the MoneyInput for the originalUnitPrice field within the DraftOrderInput.
Any insights or suggestions would be greatly appreciated. Thank you in advance for your help!
According to the docs "originalUnitPrice" is deprecated and also the type takes a number without currency.
Try either removing currency like the example in the docs.
Or use "originalUnitPriceWithCurrency" instead.
https://shopify.dev/docs/api/admin-graphql/2024-10/mutations/draftOrderCreate
Gojiberry - Best post-purchase survey and feedback app for Shopify | Install on App Store for free
Shopify Community is helpful, BUT... why not start asking your customers for feedback instead?