How to Manage Draft Orders
In this document, you’ll learn how to manage draft orders using the admin REST APIs.
Overview
Using the draft orders admin REST APIs, you can manage draft orders and perform other related functionalities.
Scenario
You want to add or use the following admin functionalities:
- Manage draft orders, including listing, creating, updating, and deleting draft orders.
- Managing line items in draft orders, including adding, updating, and deleting items from a draft order.
- Authorize and capture a draft order’s payment.
Prerequisites
Medusa Components
It is assumed that you already have a Medusa backend installed and set up. If not, you can follow our quickstart guide to get started.
JS Client
This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods.
If you follow the JS Client code blocks, it’s assumed you already have Medusa’s JS Client installed and have created an instance of the client.
Medusa React
This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods.
If you follow the Medusa React code blocks, it's assumed you already have Medusa React installed and have used MedusaProvider higher in your component tree.
Authenticated Admin User
You must be an authenticated admin user before following along with the steps in the tutorial.
You can learn more about authenticating as an admin user in the API reference.
List Draft Orders
You can list draft orders by sending a request to the List Draft Orders API Route:
import { useAdminDraftOrders } from "medusa-react"
const DraftOrders = () => {
const { draft_orders, isLoading } = useAdminDraftOrders()
return (
<div>
{isLoading && <span>Loading...</span>}
{draft_orders && !draft_orders.length && (
<span>No Draft Orders</span>
)}
{draft_orders && draft_orders.length > 0 && (
<ul>
{draft_orders.map((order) => (
<li key={order.id}>{order.display_id}</li>
))}
</ul>
)}
</div>
)
}
export default DraftOrders
This API Route doesn't require any path or query parameters. You can pass search or pagination query parameters as explained in the API reference.
The request returns an array of draft order objects along with pagination parameters.
Create a Draft Order
You can create a draft order by sending a request to the Create Draft Order API Route:
medusa.admin.draftOrders.create({
email,
region_id,
items: [
{
// defined product
quantity: 1,
variant_id,
},
{
// custom product
quantity: 1,
unit_price: 1000,
title: "Custom Product",
},
],
shipping_methods: [
{
option_id,
// for custom shipping price
price,
},
],
})
.then(({ draft_order }) => {
console.log(draft_order.id)
})
import { useAdminCreateDraftOrder } from "medusa-react"
type DraftOrderData = {
email: string
region_id: string
items: {
quantity: number,
variant_id: string
}[]
shipping_methods: {
option_id: string
price: number
}[]
}
const CreateDraftOrder = () => {
const createDraftOrder = useAdminCreateDraftOrder()
// ...
const handleCreate = (data: DraftOrderData) => {
createDraftOrder.mutate(data, {
onSuccess: ({ draft_order }) => {
console.log(draft_order.id)
}
})
}
// ...
}
export default CreateDraftOrder
fetch(`<BACKEND_URL>/admin/draft-orders`, {
credentials: "include",
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email,
region_id,
items: [
{
// defined product
quantity: 1,
variant_id,
},
{
// custom product
quantity: 1,
unit_price: 1000,
title: "Custom Product",
},
],
shipping_methods: [
{
option_id,
// for custom shipping price
price,
},
],
}),
})
.then((response) => response.json())
.then(({ draft_order }) => {
console.log(draft_order.id)
})
curl -L -X POST '<BACKEND_URL>/admin/draft-orders' \
-H 'x-medusa-access-token: <API_TOKEN>' \
-H 'Content-Type: application/json' \
--data-raw '{
"email": "<EMAIL>",
"region_id": "<REGION_ID>",
"items": [
{
"quantity": 1,
"variant_id": "<VARIANT_ID>"
},
{
"quantity": 1,
"unit_price": 1000,
"title": "Custom Product"
}
],
"shipping_methods": [
{
"option_id": "<OPTION_ID>",
"price": 1000
}
]
}'
This API Route requires the following request body parameters:
email
: a string indicating the email of the customer to associate this draft order with.region_id
: a string indicating the ID of the region this draft order belongs to.shipping_methods
: an array of objects, each object being a shipping method to use for the draft order. The object is required to have theoption_id
property which is the ID of the shipping option to use. You can optionally specify aprice
property to set a custom amount for the price.
You can also pass other optional parameters. For example, the items
array can be passed to add line items to the draft order. There are two types of items that you can add:
- Defined product variants. This is done by passing the
variant_id
property, with its value being the ID of the product variant to add. - Custom products that aren’t defined in your store. This is done by passing the
unit_price
property with its value being the price of the custom product, and thetitle
property with its value being the title of the custom product.
You must also pass for each item its quantity.
To learn about other optional request body parameters, such as passing shipping or billing addresses, check out the API reference.
The request returns the created draft order as an object.
Retrieve Draft Order
You can retrieve a draft order by sending a request to the Get Draft Order API Route:
import { useAdminDraftOrder } from "medusa-react"
type Props = {
draftOrderId: string
}
const DraftOrder = ({ draftOrderId }: Props) => {
const {
draft_order,
isLoading,
} = useAdminDraftOrder(draftOrderId)
return (
<div>
{isLoading && <span>Loading...</span>}
{draft_order && <span>{draft_order.display_id}</span>}
</div>
)
}
export default DraftOrder
This API Route requires the draft order’s ID as a path parameter.
The request returns the draft order as an object.
Update Draft Order
You can update a draft order by sending a request to the Update Draft Order API Route:
import { useAdminUpdateDraftOrder } from "medusa-react"
type Props = {
draftOrderId: string
}
const DraftOrder = ({ draftOrderId }: Props) => {
const updateDraftOrder = useAdminUpdateDraftOrder(
draftOrderId
)
// ...
const handleUpdate = (email: string) => {
updateDraftOrder.mutate({
email,
}, {
onSuccess: ({ draft_order }) => {
console.log(draft_order.id)
}
})
}
// ...
}
export default DraftOrder
This API Route requires the draft order’s ID as a path parameter.
In the request body, you can pass any of the draft order’s fields to update. In the example above, you update the email
field. Check out the API reference to learn about other accepted request body parameters.
The request returns the updated draft order as an object.
Manage Line Items
Add Line Items
You can add line items to a draft order by sending a request to the Create Line Items API Route:
import { useAdminDraftOrderAddLineItem } from "medusa-react"
type Props = {
draftOrderId: string
}
const DraftOrder = ({ draftOrderId }: Props) => {
const addLineItem = useAdminDraftOrderAddLineItem(
draftOrderId
)
// ...
const handleAdd = (quantity: number) => {
addLineItem.mutate({
quantity,
}, {
onSuccess: ({ draft_order }) => {
console.log(draft_order.cart)
}
})
}
// ...
}
export default DraftOrder
fetch(`<BACKEND_URL>/admin/draft-orders/${draftOrderId}/line-items`, {
credentials: "include",
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
quantity: 1,
}),
})
.then((response) => response.json())
.then(({ draft_order }) => {
console.log(draft_order.cart.items)
})
This API Route requires the ID of the draft order as a path parameter.
In the request body, it’s required to pass the quantity
parameter, which is a number indicating the quantity of the item in the draft order. You can also pass other optional parameters based on the type of line item you’re adding.
There are two types of items that you can add:
- Defined product variants. This is done by passing the
variant_id
parameter, with its value being the ID of the product variant to add. - Custom products that aren’t defined in your store. This is done by passing the
unit_price
parameter with its value being the price of the custom product, and thetitle
property with its value being the title of the custom product.
Check the API reference for a full list of request body parameters.
The request returns the updated draft order as an object. You can access the draft order’s items by accessing the carts
property in the draft item, then the items
property. The items
property is an array of line item objects.
Update Line Item
You can update a line item by sending a request to the Update Line Item API Route:
import { useAdminDraftOrderUpdateLineItem } from "medusa-react"
type Props = {
draftOrderId: string
}
const DraftOrder = ({ draftOrderId }: Props) => {
const updateLineItem = useAdminDraftOrderUpdateLineItem(
draftOrderId
)
// ...
const handleUpdate = (
itemId: string,
quantity: number
) => {
updateLineItem.mutate({
item_id: itemId,
quantity,
})
}
// ...
}
export default DraftOrder
fetch(`<BACKEND_URL>/admin/draft-orders/${draftOrderId}/line-items/${itemId}`, {
credentials: "include",
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
quantity: 1,
}),
})
.then((response) => response.json())
.then(({ draft_order }) => {
console.log(draft_order.cart.items)
})
This API Route requires the draft order and line item’s IDs as path parameters.
In the request body, you can pass any of the line item’s fields as parameters to update them. In the example above, you pass the quantity
parameter to update the quantity of the item. Check out the API reference for a full list of request body parameters.
The request returns the updated draft order as an object. You can access the draft order’s items by accessing the carts
property in the draft item, then the items
property. The items
property is an array of line item objects.
Delete Line Item
You can delete a line item by sending a request to the Delete Line Item API Route:
import { useAdminDraftOrderRemoveLineItem } from "medusa-react"
type Props = {
draftOrderId: string
}
const DraftOrder = ({ draftOrderId }: Props) => {
const deleteLineItem = useAdminDraftOrderRemoveLineItem(
draftOrderId
)
// ...
const handleDelete = (itemId: string) => {
deleteLineItem.mutate(itemId)
}
// ...
}
export default DraftOrder
This API Route requires the draft order and line item’s IDs as path parameters.
The request returns the updated draft order as an object. You can access the draft order’s items by accessing the carts
property in the draft item, then the items
property. The items
property is an array of line item objects.
Register Draft Order Payment
Registering the draft order’s payment leads to authorizing and capturing the payment using the system
payment method. This would complete the draft order and create an order from it.
You can register the draft order payment by sending a request to the Register Draft Order Payment API Route:
import { useAdminDraftOrderRegisterPayment } from "medusa-react"
type Props = {
draftOrderId: string
}
const DraftOrder = ({ draftOrderId }: Props) => {
const registerPayment = useAdminDraftOrderRegisterPayment(
draftOrderId
)
// ...
const handlePayment = () => {
registerPayment.mutate(void 0, {
onSuccess: ({ order }) => {
console.log(order.id)
}
})
}
// ...
}
export default DraftOrder
This API Route requires the draft order’s ID as a path parameter.
The request returns the order created from the draft order as an object.
Delete a Draft Order
You can delete a draft order by sending a request to the Delete Draft Order API Route:
import { useAdminDeleteDraftOrder } from "medusa-react"
type Props = {
draftOrderId: string
}
const DraftOrder = ({ draftOrderId }: Props) => {
const deleteDraftOrder = useAdminDeleteDraftOrder(
draftOrderId
)
// ...
const handleDelete = () => {
deleteDraftOrder.mutate(void 0, {
onSuccess: ({ id, object, deleted }) => {
console.log(id)
}
})
}
// ...
}
export default DraftOrder
This API Route requires the draft order’s ID as a path parameter.
The request returns the following fields:
id
: The ID of the deleted draft order.object
: The type of object that was deleted. In this case, the value will bedraft-order
.deleted
: A boolean value indicating whether the draft order was deleted.