Creating Orders

In this example we take you through how to create an order with the Operator API

What you’ll learn

In this article you’ll learn how to use the GraphQL orderCreate mutation, which is used when following the Connected integration pattern. Specifically, you’ll learn:

  • The order create workflow
  • High-level anatomy of an order
  • How to use the orderCreate mutation along with some tips and tricks
  • How to apply adjustments (custom fees and promotions)

The Connected Pattern

When creating a “front-end” integration using the Marketplacer GraphQL API, we distinguish between 2 common patterns:

  • Connected: Make use of an existing eCommerce front end (this takes care of cart, checkout and payment features), and “connect” into Marketplacer through an integration layer. In this pattern you simply pass completed orders to Marketplacer. This is the focus of this article.
  • Headless: A full build custom UI that made use of the Marketplacer cart and checkout functionality (this included using the payment gateways configured in Marketplacer )

Headless Vs Connected flows


From a pure API perspective the differences between the 2 integration types essentially boils down to how you would use the GraphQL API to create orders:

  • Connected Use the orderCreate mutation to directly create an order in Marketplacer (cart management, payment etc. is not visible to Marketplacer, we simply receive completed orders)
  • Headless: Used the cart based mutations to create a cart, then used the checkout mutation to complete the purchase flow. The result of a successful checkout operation was the creation of an order

These distinctions are illustrated below:

Headless Vs Connected

The ultimate goal in both cases is to create an order object in Marketplacer. Some further points to note:

  1. The Connected Integration simply creates orders, (payment, cart management is done somewhere else)
  2. The Headless front end used the Marketplacer API suite to perform cart & checkout functions.
  3. The checkout mutation relied upon 3rd party payment gateways configured in Marketplacer.

As mentioned above, Marketplacer now only supports the Connected Integration pattern which is discussed in the remainder of this article - specifically the use of the orderCreate mutation.

Anatomy of an order

At this point it’s probably worth clarifying what an order is in Marketplacer, the following diagram illustrates the high level anatomy:


Order Relationship


Put simply:

  • A Seller is an individual entity (usually a business) that the marketplace operator has invited to sell on their marketplace. Multiple sellers can “participate” in a single order.
  • An Order is the “marketplace-level” object that acts as the container for a customer’s entire purchase. An order object in Marketplacer will always have at least 1 Invoice attached to it.
  • An invoice is the individual seller’s “view” of the order. Given that we are dealing with a marketplace, it is conceivable that customers will purchase items from 1 or more Sellers. It is therefore necessary to “split” the order into seller-level components, in this case the invoice object. Even if there is only 1 seller participating in the transaction, there will still be an invoice created on the order
  • A Line Item is the individual item that a customer will purchase. Line items start their journey as Variants placed for sale on the marketplace by the seller. When a variant object is purchased a lineItem object is created.

Probably the main take-away from the previous conversation is the parent child relationship between the order and invoice objects.

Using orderCreate

An example of the orderCreate mutation is available in both our Postman and Insomnia collections, details on both can be found here. The rest of this section describes the main input components of this mutation.


The orderCreate mutation input (OrderCreateMutationInput) has the following input types of interest, we’ll cover each one in turn:

  • OrderInput
  • OrderCreateNotificationEnum
  • LineItemInput
    • If using the LineItemInput, you cannot also use InvoiceInput
  • InvoiceInput
    • If using the InvoiceInput, you cannot also use LineItemInput
    • LineItemInput can be supplied as child input type of InvoiceInput, but as stated above it cannot exist at the same level

OrderInput

This is section contains information related to the entire order, for example:

  • Customer Name
  • Customer Address
  • Customer messages / notes
  • Metadata / External Ids

OrderCreateNotifications

This describes how you’d like to (optionally) notify Sellers that they have new order, options are:

  • EMail
  • SMS

The default position is that no communications are sent to the Sellers so this has to be explicitly requested.

LineItemInput

In this section you define the order line items, the following attributes are typically defined:

  • variantId: This is the id of the variant that you wish to purchase
  • quantity: The number of line items you wish to purchase
  • cost: This is the object that holds the costs associated with each line item, broken down as:
    • amount: This is the total cost for the line item(s), not the unit price. E.g. If you have a variant priced at 1000 cents, and order 3 of them, then you’d pass 3000 as the value here
    • tax: If you have a specific tax amount for this line item it can be supplied here, otherwise you can omit and the default tax will be applied automatically by Marketplacer
  • postage: This is the object that holds the postage costs associated with each line item, broken down as:
    • amount: This is the total postage cost for all the line items
    • tax: If you have a specific tax amount for postage it can be supplied here, otherwise you can omit
  • adjustments: This object allows you to apply promotions (for each line item)
    • adjustmentType: This is mandatory and should be of type PROMOTION
    • amountCents: This must be negative and the total amount of all adjustments cannot be more than the total of the invoice.
    • amountToWithholdFromSellerRemittanceCents: must be positive and not more than the absolute amount of amountCents. This is important, the amount to withhold means that the remaining balance of the discount will be added to the remittance. E.g. If the operator was funding the entire promotion, this would need to be 0. If the cost of the discount was being borne entirely by the seller, amountToWithholdFromSellerRemittanceCents would be the absolute value of amountCents.
    • description: This is mandatory, and will be what is displayed in our UI and invoices as the reason for the promotion.
    • sourceId: This is the ID of the promotion as it exists in Marketplacer. This determines if the discount is to be applied to the shipping or the item, based on the action taken when the associated promotions was created.
  • externalIds: This is a key / value pair combination that can be used to represent 3rd party (aka “external”) Ids for each line item.
  • metadata: This is a key / value pair combination that can be used to represent any additional metadata for each line item.

Points to note

  • There has to be a sufficient stock holding for each variant you wish to purchase - this is the countOnHand attribute on each variant object
    • You cannot over-order, i.e quantity > countOnHand
    • You cannot pre-order
  • The unit of currency for both cost and postage objects is the lowest denominated unit of currency configured for the marketplace, e.g.:
    • US / Australian Dollars: Unit of currency would be cents
    • GBP Pound: Unit of currency would be pence
    • Euro: Unit of currency would be cents
  • We require a “whole cents unit price”.
    • E.g. if you supplied 10830 for the amount with a quantity of 4, this equates to an individual line item price of 2707.5 cents, (fractions of a cent are not permissible)
    • In the above case the individual line item price is rounded up to 2708, resulting in total line item amount of 10832 cents ($108.32)
  • If you choose to supply a value for tax you have to do so for both cost and postage objects you cannot just specify for one
  • If you choose to supply values for tax for 1 line item (for both cost and postage objects), you have to supply tax values for all line items on the order
  • Multiple line items from different Sellers can be added, Markerplacer will workout the “order-split” or invoice creation automatically
  • adjustments of types FEE and PROMOTION can be applied using orderCreate however the reader should be aware of the following:
    • Promotions (PROMOTION) can only be applied on Line Items (LineItemInput) and not via the Invoice (InvoiceInput)
    • Custom Fees (FEE) can only be applied on the Invoice (InvoiceInput) and not via Line Items (LineItemInput)

Example 1: Use lineItems to create a simple order

    mutation{
      orderCreate(input: {
        order: {   
          firstName: "John"
          surname: "Doe"
          phone: "0405555555"
          emailAddress: "jb@email.com"
          address: {
            address: "146 Buckhurst Street"
            city: "Melbourne"
            country: {
              code: "AU"  
            }
            postcode: "3000"
            state: {
              name: "Victoria"
            }
          }
        }
        lineItems: [
          {             
            variantId: "VmFyaWFudC03MTM3"
            quantity: 1
            cost:{
              amount: 1200
              tax: 120
            }	
          }
        ]
      })
      {
        order{
          id
          legacyId
          totalCents
        }
        status
        errors{
          field
          messages
        }
      }
    }

Example 2: Use lineItems to create an order with a promotion adjustment

In the following example of the orderCreate mutation we need to supply the sourceId which relates to the ID of the promotion as it exists in Marketplacer. An example of how you can return promotions, (specifically their IDs), is provided in the query below.

    query {
      promotions(status: "active") {
        nodes {
          id
          name
        }
      }
    }

The above query will give you all the active promotions configured on your Marketplacer instance. All we require for the adjustments input in the following mutation is an id (aka sourceId). Note: this query can return a much more complex set of data relating to each promotion, an example of which can be found in both our Postman and Insomnia collections.


An example of creating an order with a promotion is shown below:

    mutation{
      orderCreate(input: {
        order: {   
          firstName: "John"
          surname: "Doe"
          phone: "0405555555"
          emailAddress: "jb@email.com"
          address: {
            address: "146 Buckhurst Street"
            city: "Melbourne"
            country: {
              code: "AU"  
            }
            postcode: "3000"
            state: {
              name: "Victoria"
            }
          }
        }
        lineItems: [
          {             
            variantId: "VmFyaWFudC03MTM3"
            quantity: 1
            cost:{
              amount: 1200
            }
            adjustments: [
              {
                adjustmentType: PROMOTION
                amountCents: -120
                amountToWithholdFromSellerRemittanceCents: 0
                description: "10% off"
                sourceId: "UHJvbW90aW9uLTEyMA=="
              }
            ]
          }
        ]
      })
      {
        order{
          id
          legacyId
          totalCents
        }
        status
        errors{
          field
          messages
        }
      }
    }

InvoiceInput

Custom Fees One of the reasons you may want to use this approach (instead of just supplying line items) is that you may want to apply Custom Fees on the Invoice. If so, this is the only way that you can achieve that.

Using InvoiceInput is the 2nd (less popular way) to create orders as the onus on “splitting” the order into Invoices lies with the consumer of the orderCreate mutation. The following attributes are typically defined when using InvoiceInput:


  • externalIds: This is a key / value pair combination that can be used to represent 3rd party (aka “external”) Ids for each invoice.
  • metadata: This is a key / value pair combination that can be used to represent any additional metadata for each invoice.
  • lineItems: Refer to the above section on the attribute set available on the LineItemInput type.
  • adjustments: This object allows you to apply custom fees for each invoice
    • adjustmentType: This is mandatory and should be of type FEE (note you cannot apply promotions at the Invoice level, you need to make promotion adjustments at the line item level - see above example)
    • amountCents: This must be a positive amount
    • amountToWithholdFromSellerRemittanceCents: must be positive and not more than the absolute amount of amountCents. This gives you the ability to recover this fee from the seller.
    • description: This is mandatory, and will be what is displayed in our UI and invoices as the reason for the custom fee.

Example 3: Use InvoiceInput to create an order (and Invoice) with a custom fee

    mutation{
      orderCreate(input: {
        order: {   
          firstName: "John"
          surname: "Doe"
          phone: "0405510036"
          emailAddress: "jd@email.com"
          address: {
            address: "146 Buckhurst Street"
            city: "Melbourne"
            country: {
              code: "AU"  
            }
            postcode: "3000"
            state: {
              name: "Victoria"
            }
          }
        }
        invoices:[
          {
            lineItems: [
              {             
                variantId: "VmFyaWFudC03MTM3"
                quantity: 1
                cost:{
                  amount: 400
                }
              }
            ]
            adjustments:[
              {
                adjustmentType: FEE
                amountCents: 40
                amountToWithholdFromSellerRemittanceCents: 40
                description: "Remote Shipping Fee"
              }
            ]
          }
        ]
      })
      {
        order{
          id
          legacyId
          totalCents
        }
        status
        errors{
          field
          messages
        }
      }
    }

Deprecated Functionality

We have now deprecated the following functionality:

totalCents and postageCents

You used to be able to create lineitem objects by supplying values for:

  • totalCents
  • postageCents

See example below:

Headless Vs Connected

This approach as been deprecated in favour of using the following objects:

  • cost : this replaces totalCents
  • postage: this replaces postageCents