Streamlining Your Shopify Store: How to Auto-Delete Stale Draft Orders with Flow and Avoid API Errors
Hey everyone,
As a Shopify expert who spends a lot of time poring over community discussions, I often see common pain points surface that many of you are grappling with. One that recently caught my eye was from luxepalmer in the forums, asking for help with a tricky Shopify Flow error. They were trying to set up an automation to delete "stale" draft orders – a brilliant idea for keeping your admin neat and tidy, especially if you deal with lots of abandoned carts or wholesale inquiries that don't convert.
The Challenge: Deleting Stale Draft Orders with Shopify Flow
luxepalmer had a solid plan: use Shopify Flow to tag draft orders as "Stale" after 48 hours, and then another Flow to automatically delete them. Sounds straightforward, right? But they hit a snag at the "Send Admin API request" step, receiving this error: "Exception: Mutation had errors: “Variable $input of type DraftOrderDeleteInput! was provided invalid value”".
This error message is a classic indicator that the API isn't getting the data in the format it expects. It's a common hurdle when you're diving into custom API calls within Flow, and it's exactly the kind of puzzle the community loves to solve together.
Here's a peek at what luxepalmer's flow looked like initially:
Unpacking the Solution: GraphQL IDs vs. Numeric IDs
The core of the problem, as ShopIntegrations pointed out, lies in the format of the ID being sent. Shopify's Admin GraphQL API, which Flow uses for these advanced actions, expects a specific global ID (often called a GID) like gid://shopify/DraftOrder/12345, not just the plain numeric ID (12345) that you might be used to seeing in URLs or some legacy API contexts.
tim_1 further clarified this, even linking to the official draftOrderDelete GraphQL documentation, which is super helpful for understanding the expected input. They showed how an ID might look internally:
{
"id": "gid://shopify/DraftOrder/162487337014",
"legacyResourceId": "162487337014"
}
This distinction is crucial! Shopify Flow often provides the full GraphQL GID automatically, but sometimes, especially if you're pulling data from other steps or doing complex manipulations, you might end up with just the numeric legacyResourceId. If that happens, you'd need to construct the full GID yourself, as tim_1 suggested, using Liquid like this:
{
"input": {
"id": "gid://shopify/DraftOrder/{{- getDraftOrderDataForeachitem.id -}}"
}
}
The Winning Code: Direct Liquid in the Mutation
While Maximus3 provided a good general approach for the Send Admin API request step, showing how to structure the input variable, ShopIntegrations offered a slightly cleaner and more direct method that bypasses the separate variables block entirely by embedding the Liquid directly into the GraphQL mutation. This is often my preferred way to handle it for simplicity when the input is straightforward.
Here's the exact setup that luxepalmer confirmed worked for them, which I've also used successfully in my own stores to manage wholesale drafts:
1. Set up your Flow Trigger and Conditions:
- Trigger: For instance, "Draft order tagged" (when the "Stale" tag is added).
- Condition: "Draft order tag" contains "Stale".
2. Add the "Send Admin API request" action:
This is where the magic happens. In the query box, you'll paste the following GraphQL mutation. Notice how it directly uses {{ draftOrder.adminGraphqlApiId }}. This Liquid variable automatically provides the correct GraphQL ID for the draft order that triggered the flow.
graphql
mutation {
draftOrderDelete(input: {id: "{{ draftOrder.adminGraphqlApiId }}"}) {
deletedId
userErrors {
message
}
}
}
You can see how this step looks in Flow, thanks to the screenshots Maximus3 shared:
And here's the specific input structure Maximus3 showed, which also works if your Flow setup provides the getDraftOrderDataForeachitem.id in the correct GID format:
{
"input": {
"id": "{{ getDraftOrderDataForeachitem.id }}"
}
}
Just remember, the crucial part is making sure that .id or .adminGraphqlApiId variable actually contains the full gid://shopify/DraftOrder/ID_NUMBER string. If you're building a more complex Flow, always check your Flow logs to see the exact data format being passed between steps. That's your best debugging friend!
Why This Matters for Your Store
Automating the cleanup of stale draft orders isn't just about tidiness; it's about efficiency. Think about:
- Reduced Clutter: A cleaner admin interface means less time sifting through irrelevant data.
- Improved Performance: While a few extra draft orders won't break your store, consistently pruning unnecessary data can contribute to a snappier admin experience over time.
- Better Reporting: When your data is clean, your reports on active draft orders, abandoned carts, or wholesale inquiries become more accurate and actionable.
This whole discussion really highlights the power of Shopify Flow combined with the Admin API. It might seem a bit technical at first, especially when you encounter those cryptic API error messages. But as luxepalmer's success shows, with a little help from the community and an understanding of how Shopify's GraphQL API expects its IDs, you can automate some incredibly useful tasks to keep your store running smoothly.
Keep those Flows flowing, and don't hesitate to tap into the collective wisdom of the Shopify community when you hit a wall. There's always someone who's been there before and has a helpful insight to share!



