Skip to content

Recipe: Admin Create-Order Flow

Place an order for a customer from the admin side — the API equivalent of the admin panel's Create Order screen. Every request carries the admin Integration token:

Authorization: Bearer <id>|<token>

The flow builds a draft cart, fills it, then places it. Do the steps in order — the sequence is enforced (you can't set a shipping method before addresses, etc.).

The 6 steps (REST)

#StepCall
1Create a draft cart for the customerPOST /api/admin/customers/{customerId}/draft-carts → returns cartId
2Add itemsPOST /api/admin/carts/{cartId}/items
3Save billing + shipping addressesPOST /api/admin/carts/{cartId}/addresses
4List then set a shipping methodGET then POST /api/admin/carts/{cartId}/shipping-methods
5List then set a payment methodGET then POST /api/admin/carts/{cartId}/payment-methods
6Place the orderPOST /api/admin/orders/place/{cartId} → returns orderId

Open the Sales → Orders pages for the exact request bodies. Add-item bodies are product-type-specific (configurable / grouped / bundle / downloadable need their option selections). Booking products are not supported in admin Create-Order (matches the admin panel).

GraphQL variant — select result fields, never id

The draft-cart and cart-write operations are actions, not fetchable resources, so they have no selectable id. Select the result fields instead, or the query returns an internal-server error.

Step 1 — create the draft cart (select cartId, not id):

graphql
mutation CreateDraftCart($input: createAdminDraftCartInput!) {
  createAdminDraftCart(input: $input) {
    adminDraftCart {
      cartId
      customerId
      success
      message
    }
  }
}
json
{
  "input": {
    "customerId": 1
  }
}

Step 6 — place the order (select orderId, not id):

graphql
mutation PlaceOrder($input: createAdminPlaceOrderInput!) {
  createAdminPlaceOrder(input: $input) {
    adminPlaceOrder {
      orderId
      incrementId
      grandTotal
      success
      message
    }
  }
}
json
{
  "input": {
    "cartId": 42
  }
}

The intermediate cart mutations (add item, save addresses, set shipping/payment method) likewise return the updated cart payload — select the cart's contents and the success / message fields, not id.

Why id is not selectable here

Fetchable resources — a customer, a product, a placed order — have a GET /…/{id} route, so GraphQL can resolve their id. Action operations (create-draft-cart, cart writes, place-order) have no such route, so there is no id to return. Read the action's result fields (cartId, orderId, status, success, message) instead.

Status codes to handle

200/201 success · 401 unauthenticated · 403 forbidden · 404 cart/customer not found · 409 wrong step order (e.g. shipping before addresses) · 422 validation (e.g. below minimum order amount, unsupported payment method).

Released under the MIT License.