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, specifically, you’ll learn:

  • The typical way operators integrate into Marketplacer
  • 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

The typical pattern employed by a marketplace operator building an integration into Marketplacer (referred to as the Connected Pattern) involves “connecting” an existing frontend eCommerce platform with Marketplacer.

For context the primary responsibilities of each solution component, include, but are not limited to:

MarketplacerConnected IntegrationeCommerce
Host products created by SellersFacilitate the movement of products from Marketplacer to the eCommerce domainSurface products for customers to buy
Surface orders for sellers to actionFacilitate the movement of orders from the eCommerce domain to MarketplacerAccept and process payments
Create orders in Marketplacer

For a more detailed overview of the Connected Pattern, the following resources may be of use:
- Connected Integration overview video
- Connected Integration Playbook.


The focus of this article is the use of the orderCreate mutation, which allows for the direct creation of orders (post payment) on Marketplacer for downstream sellers to action.


Connected Integration


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 attach 3rd party (aka “external”) Ids for each line item at the point the order is created.
    • NOTE: External Ids are not used to reference the products you want to add to the order, for this you need to use the variantId.
  • metadata: This is a key / value pair combination that can be used to represent any additional metadata for each line item.
  • deliveryType: If not supplied this defaults to BUY_ONLINE which means the products purchased will be sent to the customer. The other values are:
    • CLICK_AND_COLLECT - customer will collect the items identified as such
    • NO_DISPATCH - Not typically used but relates to items that are nor delivered or picked up, e.g. digital downloads.

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
  }
 }
}

Example 3 Create a click and collect order

In this example we override the default deliveryType for the line items (BUY_ONLINE - which means items will be delivered via post), instead specifying the item is for collection (CLICK_AND_COLLECT).

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 }
     deliveryType: CLICK_AND_COLLECT
    }
   ]
  }
 ) {
  order {
   id
   legacyId
   totalCents
  }
  status
  errors {
   field
   messages
  }
 }
}

NOTE: If you supply multiple line items with different deliveryTypes e.g.:

  • Line Item 1: deliveryType = BUY_ONLINE
  • LIne Item 2: deliveryType = CLICK_AND_COLLECT
  • Line Item 3: deliveryType = CLICK_AND_COLLECT

This will result in 2 Invoices being created:

  • Invoice 1: Line Item 1 (BUY_ONLIINE)
  • Invoice 2: Line Item 2 and Line Item 3 (CLICK_AND_COLLECT)

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
        }
      }
    }