30 June 2022
CartsOrdersPricing and DiscountsExtensibilityGraphQL
We have released Quotes in public beta. This new feature allows you to negotiate quote requests for your products with your customers. The negotiation process involves utilizing several APIs that we introduced with this feature, allowing you to control each step of the intended workflow of the negotiation. All the introduced resources, such as Quote Request, Staged Quote, and Quote can be extended with Custom Fields. The discounts applied on a specific Quote, can be utilized by the newly added DirectDiscount. After successful negotiation, the Order can be created right from the Quote.
Changes:
- [API] Added Quote Requests and My Quote Requests APIs.
 - [API] Added Staged Quotes API.
 - [API] Added Quotes API.
 - [API] Added QuoteRequestCreated, QuoteRequestStateChanged, and QuoteRequestDeleted Messages.
 - [API] Added StagedQuoteCreated, StagedQuoteStateChanged, StagedQuoteValidToSet, StagedQuoteSellerCommentSet, and StagedQuoteDeleted Messages.
 - [API] Added QuoteCreated, QuoteStateChanged, and QuoteDeleted Messages.
 - [API] Added 
Quoteto CartOrigin. - [API] Added DirectDiscount and DirectDiscountDraft to Carts API.
 - [API] Added 
directDiscountsfield to Cart and Order. - [API] Added 
setDirectDiscountsupdate action to Carts and Orders via OrderEdit. - [API] Added OrderFromQuoteDraft and Create Order from Quote endpoint to Orders API.
 - [API] Added 
quotefield to Order. - [API] Added OAuth scopes 
manage_quote_requests,view_quote_requests,manage_my_quote_requests,manage_staged_quotes,view_staged_quotes,manage_quotes, andview_quotes. - [GraphQL API] Added the following types to the GraphQL schema: 
CancelQuoteRequest,ChangeMyQuoteMyQuoteState,ChangeQuoteRequestState,ChangeQuoteState,ChangeStagedQuoteState,MyQuoteRequestDraft,MyQuoteRequestUpdateAction,MyQuoteState,MyQuoteUpdateAction,OrderMyQuoteCommand,OrderQuoteCommand,Quote,QuoteDraft,QuoteQueryResult,QuoteRequest,QuoteRequestDraft,QuoteRequestQueryResult,QuoteRequestState,QuoteRequestUpdateAction,QuoteState,QuoteUpdateAction,SetMyQuoteRequestCustomField,SetMyQuoteRequestCustomType,SetQuoteCustomField,SetQuoteCustomType,SetQuoteRequestCustomField,SetQuoteRequestCustomType,SetStagedQuoteCustomField,SetStagedQuoteCustomType,SetStagedQuoteSellerComment,SetStagedQuoteValidTo,StagedQuote,StagedQuoteDraft,StagedQuoteQueryResult,StagedQuoteState,StagedQuoteUpdateAction. 
- [GraphQL API] Changed the 
Querytype:- Added the 
quoteRequestfield to theQuerytype. - Added the 
quotesfield to theQuerytype. - Added the 
stagedQuotesfield to theQuerytype. - Added the 
quotefield to theQuerytype. - Added the 
quoteRequestsfield to theQuerytype. - Added the 
stagedQuotefield to theQuerytype. 
 - Added the 
 - [GraphQL API] Changed the 
Metype:- Added the 
quoteRequestsfield to theMetype. - Added the 
quoteRequestfield to theMetype. - Added the 
quotefield to theMetype. - Added the 
quotesfield to theMetype. 
 - Added the 
 - [GraphQL API] Changed the 
Mutationtype:- Added the 
createQuoteRequestfield to theMutationtype. - Added the 
updateQuoteRequestfield to theMutationtype. - Added the 
updateMyQuoteRequestfield to theMutationtype. - Added the 
createOrderFromQuotefield to theMutationtype. - Added the 
updateQuotefield to theMutationtype. - Added the 
deleteQuoteRequestfield to theMutationtype. - Added the 
createStagedQuotefield to theMutationtype. - Added the 
updateMyQuotefield to theMutationtype. - Added the 
deleteStagedQuotefield to theMutationtype. - Added the 
createQuotefield to theMutationtype. - Added the 
updateStagedQuotefield to theMutationtype. - Added the 
createMyQuoteRequestfield to theMutationtype. - Added the 
createMyOrderFromQuotefield to theMutationtype. - Added the 
deleteQuotefield to theMutationtype. 
 - Added the 
 
The following changes were introduced in terms of GraphQL SDL:
extend type Query {
  quote(
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): Quote
  quoteRequest(
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): QuoteRequest
  quoteRequests(where: String, sort: [String!], limit: Int, offset: Int): QuoteRequestQueryResult!
  quotes(where: String, sort: [String!], limit: Int, offset: Int): QuoteQueryResult!
  stagedQuote(
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): StagedQuote
  stagedQuotes(where: String, sort: [String!], limit: Int, offset: Int): StagedQuoteQueryResult!
}
extend type Me {
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  quote(
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): Quote
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  quoteRequest(
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): QuoteRequest
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  quoteRequests(where: String, sort: [String!], limit: Int, offset: Int): QuoteRequestQueryResult!
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  quotes(where: String, sort: [String!], limit: Int, offset: Int): QuoteQueryResult!
}
extend type Mutation {
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  createMyOrderFromQuote(draft: OrderMyQuoteCommand!): Order
  createMyQuoteRequest(draft: MyQuoteRequestDraft!): QuoteRequest
  createOrderFromQuote(draft: OrderQuoteCommand!): Order
  createQuote(draft: QuoteDraft!): Quote
  createQuoteRequest(draft: QuoteRequestDraft!): QuoteRequest
  createStagedQuote(draft: StagedQuoteDraft!): StagedQuote
  deleteQuote(version: Long!, personalDataErasure: Boolean = false,
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): Quote
  deleteQuoteRequest(version: Long!, personalDataErasure: Boolean = false,
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): QuoteRequest
  deleteStagedQuote(version: Long!, personalDataErasure: Boolean = false,
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): StagedQuote
  updateMyQuote(version: Long!, actions: [MyQuoteUpdateAction!]!,
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): Quote
  updateMyQuoteRequest(version: Long!, actions: [MyQuoteRequestUpdateAction!]!,
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): QuoteRequest
  updateQuote(version: Long!, actions: [QuoteUpdateAction!]!,
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): Quote
  updateQuoteRequest(version: Long!, actions: [QuoteRequestUpdateAction!]!,
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): QuoteRequest
  updateStagedQuote(version: Long!, actions: [StagedQuoteUpdateAction!]!,
    "Queries with specified ID"
    id: String,
    "Queries with specified key"
    key: String): StagedQuote
}
input CancelQuoteRequest {
  dummy: String
}
input ChangeMyQuoteMyQuoteState {
  quoteState: MyQuoteState!
}
input ChangeQuoteRequestState {
  quoteRequestState: QuoteRequestState!
}
input ChangeQuoteState {
  quoteState: MyQuoteState!
}
input ChangeStagedQuoteState {
  stagedQuoteState: StagedQuoteState!
}
input MyQuoteRequestDraft {
  cartId: String!
  comment: String
  cartVersion: Long!
}
input MyQuoteRequestUpdateAction {
  cancelQuoteRequest: CancelQuoteRequest
  setCustomField: SetMyQuoteRequestCustomField
  setCustomType: SetMyQuoteRequestCustomType
}
enum MyQuoteState {
  Accepted
  Declined
  Failed
}
input MyQuoteUpdateAction {
  changeMyQuoteState: ChangeMyQuoteMyQuoteState
  setCustomField: SetQuoteCustomField
  setCustomType: SetQuoteCustomType
}
input OrderMyQuoteCommand {
  id: String!
  version: Long!
}
input OrderQuoteCommand {
  quote: ResourceIdentifierInput
  version: Long!
  paymentState: PaymentState
  orderState: OrderState
  state: ReferenceInput
  shipmentState: ShipmentState
  orderNumber: String
  custom: CustomFieldsDraft
}
type Quote implements Versioned {
  customerRef: Reference
  customer: Customer
  lineItems(
    "Queries with specified ID"
    id: String): [LineItem!]!
  customLineItems: [CustomLineItem!]!
  totalPrice: Money!
  taxedPrice: TaxedPrice
  shippingAddress: Address
  billingAddress: Address
  itemShippingAddresses: [Address!]!
  inventoryMode: InventoryMode!
  taxMode: TaxMode!
  taxRoundingMode: RoundingMode!
  taxCalculationMode: TaxCalculationMode!
  country: Country
  shippingInfo: ShippingInfo
  paymentInfo: PaymentInfo
  shippingRateInput: ShippingRateInput
  storeRef: KeyReference
  store: Store
  key: String
  quoteState: QuoteState!
  stagedQuoteRef: Reference!
  stagedQuote: StagedQuote
  quoteRequestRef: Reference!
  quoteRequest: QuoteRequest
  validTo: DateTime
  custom: CustomFieldsType
  id: String!
  version: Long!
  createdAt: DateTime!
  lastModifiedAt: DateTime!
  createdBy: Initiator
  lastModifiedBy: Initiator
}
input QuoteDraft {
  key: String
  stagedQuote: ResourceIdentifierInput
  stagedQuoteVersion: Long
  custom: CustomFieldsDraft
}
type QuoteQueryResult {
  offset: Int!
  count: Int!
  total: Long!
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  exists: Boolean!
  results: [Quote!]!
}
type QuoteRequest implements Versioned {
  customerRef: Reference
  customer: Customer
  lineItems(
    "Queries with specified ID"
    id: String): [LineItem!]!
  customLineItems: [CustomLineItem!]!
  totalPrice: Money!
  taxedPrice: TaxedPrice
  shippingAddress: Address
  billingAddress: Address
  itemShippingAddresses: [Address!]!
  inventoryMode: InventoryMode!
  taxMode: TaxMode!
  taxRoundingMode: RoundingMode!
  taxCalculationMode: TaxCalculationMode!
  country: Country
  shippingInfo: ShippingInfo
  paymentInfo: PaymentInfo
  shippingRateInput: ShippingRateInput
  storeRef: KeyReference
  store: Store
  key: String
  quoteRequestState: QuoteRequestState!
  comment: String
  custom: CustomFieldsType
  id: String!
  version: Long!
  createdAt: DateTime!
  lastModifiedAt: DateTime!
  createdBy: Initiator
  lastModifiedBy: Initiator
}
input QuoteRequestDraft {
  key: String
  cart: ResourceIdentifierInput
  comment: String
  cartVersion: Long
  custom: CustomFieldsDraft
}
type QuoteRequestQueryResult {
  offset: Int!
  count: Int!
  total: Long!
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  exists: Boolean!
  results: [QuoteRequest!]!
}
enum QuoteRequestState {
  Closed
  UnderReview
  Submitted
  Cancelled
  Accepted
  Rejected
}
input QuoteRequestUpdateAction {
  changeQuoteRequestState: ChangeQuoteRequestState
  setCustomField: SetQuoteRequestCustomField
  setCustomType: SetQuoteRequestCustomType
}
enum QuoteState {
  Accepted
  Declined
  Failed
  Pending
  Withdrawn
}
input QuoteUpdateAction {
  changeQuoteState: ChangeQuoteState
  setCustomField: SetQuoteCustomField
  setCustomType: SetQuoteCustomType
}
input SetMyQuoteRequestCustomField {
  name: String!
  value: String
}
input SetMyQuoteRequestCustomType {
  fields: [CustomFieldInput!]
  type: ResourceIdentifierInput
  typeKey: String
  typeId: String
}
input SetQuoteCustomField {
  name: String!
  value: String
}
input SetQuoteCustomType {
  fields: [CustomFieldInput!]
  type: ResourceIdentifierInput
  typeKey: String
  typeId: String
}
input SetQuoteRequestCustomField {
  name: String!
  value: String
}
input SetQuoteRequestCustomType {
  fields: [CustomFieldInput!]
  type: ResourceIdentifierInput
  typeKey: String
  typeId: String
}
input SetStagedQuoteCustomField {
  name: String!
  value: String
}
input SetStagedQuoteCustomType {
  fields: [CustomFieldInput!]
  type: ResourceIdentifierInput
  typeKey: String
  typeId: String
}
input SetStagedQuoteSellerComment {
  sellerComment: String
}
input SetStagedQuoteValidTo {
  validTo: DateTime
}
type StagedQuote implements Versioned {
  key: String
  stagedQuoteState: StagedQuoteState!
  quoteRequestRef: Reference!
  quoteRequest: QuoteRequest
  quotationCartRef: Reference!
  quotationCart: Cart
  customerRef: Reference
  customer: Customer
  validTo: DateTime
  custom: CustomFieldsType
  id: String!
  version: Long!
  createdAt: DateTime!
  lastModifiedAt: DateTime!
  createdBy: Initiator
  lastModifiedBy: Initiator
}
input StagedQuoteDraft {
  key: String
  quoteRequest: ResourceIdentifierInput
  quoteRequestVersion: Long
  custom: CustomFieldsDraft
}
type StagedQuoteQueryResult {
  offset: Int!
  count: Int!
  total: Long!
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  exists: Boolean!
  results: [StagedQuote!]!
}
enum StagedQuoteState {
  Closed
  InProgress
  Sent
}
input StagedQuoteUpdateAction {
  changeStagedQuoteState: ChangeStagedQuoteState
  setSellerComment: SetStagedQuoteSellerComment
  setCustomField: SetStagedQuoteCustomField
  setCustomType: SetStagedQuoteCustomType
  setValidTo: SetStagedQuoteValidTo
}