View Categories

Launching soon on the Shopify App StoreJoin the waitlist

GraphQL API reference: add-on apps

14 min read

The GraphQL operations of the add-on apps. They use the same address, keys and rules as Rentals & Bookings: see GraphQL API reference: Rentals & Bookings for how to send a request, and the API overview for keys, limits and errors.

Each section needs its app. The operations of an app the store doesn’t have are refused before anything runs, with errors[].extensions.code: "app_not_installed" and data.app naming the app. Every operation here needs a secret key; mutations need Allow changes (write). rentalApiCaller { installedApps } lists the apps your key can reach.

SectionNeeds the appdata.app
Rental ContractsRental Contractscontracts
Security DepositsSecurity Depositsdeposits
Custom FieldsCustom Fields (Fields, Waiver & ID)fields
QuotesSI Request a Quote, Hide Pricequotes
curl -s "https://YOUR-API-ADDRESS/graphql/2026-10" -H "Authorization: Bearer sirb_your_secret_key" -H "Content-Type: application/json" \
  -d '{"query": "{ salesQuotes(first: 5) { totalCount } }"}'
# 200, on a store without SI Request a Quote:
{"errors": [{"message": "This store does not have the SI Request a Quote, Hide Price app installed, so its operations are not available.",
             "locations": [{"line": 1, "column": 3}],
             "extensions": {"code": "app_not_installed", "http_status": 403, "data": {"app": "quotes"}}}]}

Rental Contracts #

Needs the Rental Contracts app. Ids are gid://sirentals/Contract/… or the agreement’s own id (as in the order’s _contract attribute). The PDF link in pdf works for 10 minutes without a key, and downloads are recorded in the audit trail. When the stored PDF no longer matches its hash, pdf is null with an altered error in errors, and the rest of the agreement still comes back.

OperationArgumentsWhat it does
rentalContracts
query · secret key
returns RentalContractConnection!
filter: RentalContractFilterInput
first: Int
after: String
last: Int
before: String
Signed rental agreements, newest first, by status, order, or a search on the order name, signer name or email.
rentalContract
query · secret key
returns RentalContract
id: ID!One agreement with its signing details, evidence, items, audit trail and a 10-minute PDF link; null when there is none.
rentalOrderContract
query · secret key
returns RentalContract
orderId: ID!An order’s agreement and its signing status; null when the order has none.
verifyRentalContract
mutation · secret key
returns RentalContractVerifyPayload!
id: ID!Check the stored PDF’s hash, the terms’ hash and the audit chain again. The check is recorded in the trail.
resendRentalContract
mutation · secret key
returns RentalContractResendPayload!
id: ID!Email the signed copy to the signer again.
query Signed {
  rentalOrderContract(orderId: "gid://shopify/Order/5550001") {
    publicId status signerName signedAt method storedCopy
    pdf { kind url expiresAt }        # kind "signed", or "preview" before a copy is stored
    auditTrail { event at }
  }
}

verifyRentalContract(id: "…") { verification { ok fileHashOk chainOk termsHashOk } } checks the evidence again; resendRentalContract emails the signed copy to the signer again.

RentalContractFilterInput

FieldTypeNotes
statusRentalContractStatus
searchStringOrder name, signer name or email.
orderIdID
EnumValues
RentalContractStatusSIGNED – Signed; the order isn’t placed (or linked) yet.
LINKED – Linked to its order.
REDACTED – Personal data removed (a customer’s redaction request or the retention period).
TypeFields
RentalContract
A signed rental agreement: who signed, when, how, what, and the evidence.
id: ID!, publicId: String!, status: RentalContractStatus!, method: String, methodLabel: String, signerName: String, signerEmail: String, signedAt: String, signedAtLabel: String, orderId: ID, orderName: String, customerId: ID, hasPdf: Boolean!, redacted: Boolean!, signatureId: String, ip: String, userAgent: String, typedName: String, hasDrawing: Boolean, consentText: String, termsSha256: String, pdfSha256: String, pdfSha256Unsigned: String, pdfGeneratedAt: String, pdfError: String, emailedAt: String, emailError: String, linkedAt: String, storedCopy: String, items: JSON, auditTrail: [RentalContractAuditEntry!]!, pdf: RentalContractFile
RentalContractAuditEntryevent: String!, label: String, at: String, detail: String, hash: String
RentalContractFilekind: String!, url: String!, expiresAt: String!
RentalContractVerifyPayloadverification: RentalContractVerification, contract: RentalContract, userErrors: [RentalUserError!]!
RentalContractVerification
The result of a verification.
ok: Boolean!, redacted: Boolean!, file: Boolean!, fileHashOk: Boolean, termsHashOk: Boolean, chainOk: Boolean!, storedHash: String, computedHash: String, checkedAt: String, chain: JSON
RentalContractResendPayloadsent: Boolean, contract: RentalContract, userErrors: [RentalUserError!]!

Security Deposits #

Needs the Security Deposits app. Refunds go to the original payment method. The app sends Shopify an idempotency key built from the order, the deposits and what they had refunded before, so a retried request can’t refund twice; a deposit already refunded answers nothing_to_refund. Amounts are decimal strings.

OperationArgumentsWhat it does
rentalOrderDeposits
query · secret key
returns RentalOrderDeposits!
orderId: ID!
refresh: Boolean = false
An order’s deposits: held, refunded, remaining, and when the rest is refunded automatically.
rentalDepositProducts
query · secret key
returns [RentalProductDepositRule!]!
–The products with their own deposit rule (the others use the store default).
rentalProductDepositRule
query · secret key
returns RentalProductDepositRule!
productId: ID!A product’s deposit rule: its own, or the store default (source).
refundRentalDeposits
mutation · secret key
returns RentalDepositRefundPayload!
input: RentalDepositRefundInput!Refund deposits to the original payment method: all of the order’s, or part of one (amount), or all but an amount you keep (keep).
setRentalDepositAutoRefund
mutation · secret key
returns RentalOrderDepositsPayload!
orderId: ID!
enabled: Boolean
Refund this order’s deposits automatically after the return (true / false), or follow the store setting (null).
setRentalProductDepositRule
mutation · secret key
returns RentalProductDepositRulePayload!
productId: ID!
input: RentalDepositRuleInput!
Give a product its own deposit rule.
removeRentalProductDepositRule
mutation · secret key
returns RentalProductDepositRuleRemovePayload!
productId: ID!Put a product back on the store default rule.
mutation Refund {
  refundRentalDeposits(input: {orderId: "5550001", depositIds: ["gid://sirentals/Deposit/17"], keep: "50.00", reason: "Scratched frame"}) {
    refund { refundId amount }
    order { status totals { total refunded remaining } deposits { title status remaining } }
    userErrors { code field message }   # bad_keep, nothing_to_refund, no_payment, refund_failed …
  }
}

RentalDepositRefundInput

FieldTypeNotes
orderIdID!
depositIds[ID!]The deposits to refund; none = every deposit of the order.
amountStringRefund this much of ONE deposit (decimal string, e.g. “150.00”).
keepStringOr keep this much of ONE deposit and refund the rest.
reasonStringShown on the refund in Shopify.

RentalDepositRuleInput

FieldTypeNotes
modeRentalDepositMode!
amountStringRequired unless mode is OFF or per is ORDER; a percentage is at most 100.
perRentalDepositPer = LINE
titleStringThe product’s title, for the list.
EnumValues
RentalDepositModeOFF – No deposit.
FIXED – A fixed amount.
PERCENT – A percentage of the rental’s unit price.
RentalDepositPerUNIT – Per unit (times the quantity).
LINE – Once per cart line.
ORDER – Joins the one deposit per order.
TypeFields
RentalOrderDeposits
An order’s deposits.
orderId: ID!, orderName: String, currency: String, deposits: [RentalDeposit!]!, totals: RentalDepositTotals!, status: RentalDepositStatus, statusLabel: String, canRefund: Boolean!, autoRefund: RentalDepositAutoRefund!
RentalDeposit
One deposit line of an order.
id: ID!, legacyResourceId: Int!, lineItemId: ID, title: String!, kind: String, quantity: Int, amount: String, tax: String, total: String!, refunded: String!, remaining: String!, currency: String, status: RentalDepositStatus!, statusLabel: String, autoRefund: Boolean!, returnedAt: String, releaseAfter: String, refundedAt: String, autoError: String, log: [RentalDepositLogEntry!]!
RentalDepositLogEntryat: String, amount: String, kept: String, reason: String, automatic: Boolean!
RentalDepositTotalstotal: String!, refunded: String!, remaining: String!
RentalDepositAutoRefundstore: Boolean!, override: Boolean, effective: Boolean!, days: Int!, releaseAfter: String, returned: Boolean!
RentalProductDepositRule
A product’s deposit rule.
productId: ID!, title: String, source: String!, rule: RentalDepositRule!
RentalDepositRulemode: RentalDepositMode!, amount: String!, per: RentalDepositPer!
RentalDepositRefundPayloadrefund: RentalDepositRefund, order: RentalOrderDeposits, userErrors: [RentalUserError!]!
RentalDepositRefundrefundId: ID, amount: String!, depositIds: [ID!]!
RentalOrderDepositsPayloadorder: RentalOrderDeposits, userErrors: [RentalUserError!]!
RentalProductDepositRulePayloaddepositRule: RentalProductDepositRule, warning: String, userErrors: [RentalUserError!]!
RentalProductDepositRuleRemovePayloadremoved: Boolean, userErrors: [RentalUserError!]!
EnumValues
RentalDepositStatusNOT_REFUNDED
PARTIALLY_REFUNDED
FULLY_REFUNDED

Custom Fields #

Needs the Custom Fields app (Fields, Waiver & ID). It works on a store without Rentals & Bookings: make the key on its API access page. ID verification is a status only (NONE, PENDING, VERIFIED, REJECTED or EXPIRED, with the document’s printed expiry date): the API never returns an ID document, an image, a file link or a document id.

OperationArgumentsWhat it does
rentalOrderFields
query · secret key
returns RentalOrderFields!
orderId: ID!
refresh: Boolean = false
An order’s answers (per line and for the whole cart), the fees they added, the damage waiver line and the ID check’s status. recorded: false when the app has nothing for the order.
rentalFieldGroups
query · secret key
returns [RentalFieldGroup!]!
–The field groups and their questions, in the order the storefront shows them.
rentalFieldGroup
query · secret key
returns RentalFieldGroup
id: ID!One field group, or null.
rentalCustomerIdVerification
query · secret key
returns RentalIdVerification!
customerId: ID!A customer’s ID verification status. Never a document, an image or a file.
rentalFieldsDefinitionsExport
query · secret key
returns RentalFieldsFile!
input: RentalFieldsDefinitionsExportInput!The question definitions as a file: JSON (lossless, to copy to another store or keep as a backup) or CSV (to edit in a spreadsheet).
createRentalFieldsImport
mutation · secret key
returns RentalFieldsImportPayload!
input: RentalFieldsImportCreateInput!Upload a definitions file (JSON or CSV, at most 5 MB). It is checked in the background: read it with rentalFieldsImport until its status is PREVIEW or FAILED.
rentalFieldsImport
query · secret key
returns RentalFieldsImport
id: ID!One import: its checked plan, errors and warnings, or its result.
rentalFieldsImports
query · secret key
returns [RentalFieldsImport!]!
first: Int = 20The latest imports, newest first.
recheckRentalFieldsImport
mutation · secret key
returns RentalFieldsImportPayload!
id: ID!Check an import again (after STALE: the field groups changed since the check).
applyRentalFieldsImport
mutation · secret key
returns RentalFieldsImportPayload!
id: ID!
planHash: String!
Apply the plan the preview showed (planHash must be that preview’s). All or nothing, in the background: read the import until APPLIED, FAILED or STALE.
cancelRentalFieldsImport
mutation · secret key
returns RentalFieldsImportPayload!
id: ID!Drop an import that wasn’t applied.
createRentalFieldsAnswersExport
mutation · secret key
returns RentalFieldsAnswersExportPayload!
input: RentalFieldsAnswersExportInput!Make a CSV of the answers customers gave on orders in a date range (confirm: true: it holds personal data). Read it with rentalFieldsAnswersExport until READY.
rentalFieldsAnswersExport
query · secret key
returns RentalFieldsAnswersExport
id: ID!One answers export; while READY, a fresh 15-minute downloadUrl on every read.
rentalFieldsAnswersExports
query · secret key
returns [RentalFieldsAnswersExport!]!
first: Int = 20The latest answers exports, newest first.
updateRentalFieldsOptionsSettings
mutation · secret key
returns RentalFieldsOptionsSettingsPayload!
input: RentalFieldsOptionsSettingsInput!Whether priced options on products that aren’t rentals are taxed.
query OrderAnswers {
  rentalOrderFields(orderId: "5550001") {
    recorded name
    lines { title answers { label value } fees { label amount } }
    cartAnswers
    waiver { state amount label }
    idVerification { mode status expiresAt }
  }
  rentalCustomerIdVerification(customerId: "555001") { status expiresAt }
}

Imports and answer exports run in the background: create one, then read it until its status settles. A preview expires after 24 hours; an answers file is deleted 24 hours after it is ready.

RentalFieldsDefinitionsExportInput

FieldTypeNotes
formatRentalFieldsDefinitionsFormat!
groupIds[ID!]Only these field groups (their numeric ids); all when left out.
includeSettingsBoolean = falseAlso the damage waiver, ID check, priced-option and message settings (JSON only; never the ID staff email).

RentalFieldsImportCreateInput

FieldTypeNotes
filenameString!
contentString!The file’s text (UTF-8, at most 5 MB).
formatRentalFieldsImportFormat = AUTO
conflictRentalFieldsImportConflict = SKIP
importDisabledBooleanTurn imported groups off so they can be checked first. Left out: on for a file from another store, off for this store’s.
includeSettingsBoolean = falseAlso import the waiver, ID, priced-option and message settings of a JSON file (never an ID staff email).

RentalFieldsAnswersExportInput

FieldTypeNotes
fromString!First day (YYYY-MM-DD, the store’s time zone).
toString!Last day (YYYY-MM-DD); at most 366 days after from.
layoutRentalFieldsAnswersLayout = WIDE
groupKeys[String!]Only the questions of these field groups (their keys); every answer when left out.
includeCartAnswersBoolean = trueAlso the cart page questions (one row per order in the wide layout).
includeCustomerIdBoolean = false
confirmBoolean!Must be true: the file holds what customers typed.

RentalFieldsOptionsSettingsInput

FieldTypeNotes
taxableBoolean!Charge tax on priced options of products that aren’t rentals.
EnumValues
RentalFieldsDefinitionsFormatJSON
CSV
RentalFieldsImportFormatAUTO – By the file name and its first character.
JSON
CSV
RentalFieldsImportConflictSKIP – Keep the store’s group.
REPLACE – Replace the store’s group and its whole question list.
COPY – Import a copy with new keys (key_2, …; question keys renamed and the rules that name them rewritten).
RentalFieldsAnswersLayoutWIDE – One row per order line with answers (and one row per order for the cart questions), a column per question.
LONG – One row per answer.
TypeFields
RentalOrderFields
What the Fields, Waiver & ID app recorded for an order.
orderId: ID!, recorded: Boolean!, name: String, lines: [RentalFieldsLine!]!, cartAnswers: JSON, waiver: RentalDamageWaiver, idVerification: RentalIdVerification, feesTotal: String!, currency: String, syncedAt: String
RentalFieldsLinekind: String, title: String!, variantTitle: String, quantity: Int, answers: [RentalFieldAnswer!]!, fees: [RentalFieldFee!]!
RentalFieldAnswerlabel: String!, value: JSON
RentalFieldFeelabel: String!, amount: String!
RentalDamageWaiverstate: String!, amount: String!, label: String
RentalIdVerification
An ID verification STATUS. Never a document, an image or a file.
customerId: ID, mode: String!, status: RentalIdStatus!, expiresAt: String
RentalFieldGroup
A group of custom fields shown on products (and at checkout).
id: ID!, legacyResourceId: Int!, key: String, name: String!, description: String, enabled: Boolean!, placement: String, scope: String, collections: [String!]!, products: [String!]!, tags: [String!], productTypes: [String!], checkoutCheck: String, position: Int!, fields: [RentalFieldDefinition!]!
RentalFieldDefinition
One custom field.
id: ID!, key: String!, type: String!, label: String!, help: String, placeholder: String, required: Boolean!, options: JSON, price: String, priceType: String, chargePer: String, conditions: JSON, min: Float, max: Float, maxlength: Int, audience: String, definition: JSON!
RentalFieldsFile
A file, as text.
filename: String!, contentType: String!, byteSize: Int!, content: String!
RentalFieldsImportPayloadimport: RentalFieldsImport, userErrors: [RentalUserError!]!
RentalFieldsImportid: ID!, status: RentalFieldsImportStatus!, format: RentalFieldsImportFormat!, filename: String!, byteSize: Int!, conflict: RentalFieldsImportConflict!, importDisabled: Boolean, includeSettings: Boolean!, sourceShop: String, sourceVersion: Int, planHash: String, counts: RentalFieldsImportCounts, plan: [RentalFieldsImportGroupPlan!]!, settings: [String!]!, messages: [RentalFieldsImportMessage!]!, createdAt: String!, createdBy: String, appliedAt: String, expiresAt: String
RentalFieldsImportCountsgroups: Int!, fields: Int!, create: Int!, replace: Int!, skip: Int!, copy: Int!, errors: Int!, warnings: Int!
RentalFieldsImportGroupPlankey: String!, name: String!, action: RentalFieldsImportAction!, newKey: String, fields: Int!, options: Int!, enabled: Boolean!, unmatched: [RentalFieldsUnmatchedRef!]!, messages: [RentalFieldsImportMessage!]!
RentalFieldsUnmatchedRef
A product or collection of the file that this store doesn’t have.
kind: String!, handle: String, title: String
RentalFieldsImportMessageseverity: RentalFieldsMessageSeverity!, code: String!, message: String!, path: String, row: Int, column: String, groupKey: String, fieldKey: String
RentalFieldsAnswersExportPayloadexport: RentalFieldsAnswersExport, userErrors: [RentalUserError!]!
RentalFieldsAnswersExportid: ID!, status: RentalFieldsExportStatus!, from: String, to: String, layout: RentalFieldsAnswersLayout!, rows: Int, byteSize: Int, downloadUrl: String, createdAt: String!, createdBy: String, expiresAt: String, error: String
RentalFieldsOptionsSettingsPayloadoptions: RentalFieldsOptionsSettings, userErrors: [RentalUserError!]!
RentalFieldsOptionsSettingstaxable: Boolean!
EnumValues
RentalIdStatusNONE
PENDING
VERIFIED
REJECTED
EXPIRED
RentalFieldsImportStatusQUEUED
CHECKING
PREVIEW – Checked: the plan, errors and warnings are ready. Apply it with applyRentalFieldsImport (not while there are errors).
STALE – The field groups changed since the check: check again (recheckRentalFieldsImport).
FAILED
APPLYING
APPLIED
CANCELLED
EXPIRED – The preview expired (24 hours) and its file was deleted.
RentalFieldsImportActionCREATE
REPLACE
SKIP
COPY
RentalFieldsMessageSeverityERROR
WARNING
RentalFieldsExportStatusQUEUED
RUNNING
READY
FAILED
EXPIRED – Deleted (24 hours after it was ready, or because a customer’s data was erased).

Quotes #

Needs the SI Request a Quote, Hide Price app. It works on a store without Rentals & Bookings: make the key on its API access page. If the store’s Quotes plan doesn’t include API access, the operations answer plan_required. Ids are gid://sirentals/SalesQuote/<id>; salesQuote(id:) also takes the number (Q-1042) or the public id. Lines keep Shopify’s gid://shopify/ProductVariant/…. The codes are the REST API’s: invalid, invalid_status, not_found, plan_required, shopify_error.

OperationArgumentsWhat it does
salesQuotes
query · secret key
returns SalesQuoteConnection!
filter: SalesQuoteFilterInput
first: Int
after: String
last: Int
before: String
The store’s quotes, newest first, by status, source, customer, a search or a change date.
salesQuote
query · secret key
returns SalesQuote
id: ID!One quote by id, number (Q-1042) or public id, with its versions, events, notes and emails; null when there is none.
createSalesQuote
mutation · secret key
returns SalesQuotePayload!
input: SalesQuoteCreateInput!Create a quote: DRAFT (you prepare it; nothing is emailed until it is sent, or send: true) or REQUEST (as if the customer asked).
updateSalesQuote
mutation · secret key
returns SalesQuotePayload!
id: ID!
input: SalesQuoteUpdateInput!
Change the working version. A sent version never changes: editing it starts the next version.
sendSalesQuote
mutation · secret key
returns SalesQuotePayload!
id: ID!Send the working version to the customer.
cancelSalesQuote
mutation · secret key
returns SalesQuotePayload!
id: ID!
reason: String
Withdraw a quote that isn’t accepted yet.
reopenSalesQuote
mutation · secret key
returns SalesQuotePayload!
id: ID!Reopen an expired, declined, rejected or cancelled quote.
convertSalesQuote
mutation · secret key
returns SalesQuoteConvertPayload!
id: ID!
mode: SalesQuoteConvertMode = INVOICE
Turn the sent version into a Shopify draft order: INVOICE (the customer gets the payment link) or ORDER (the order is made now, payment pending).
addSalesQuoteNote
mutation · secret key
returns SalesQuoteMessagePayload!
id: ID!
body: String!
Add an internal note (staff only).
addSalesQuoteMessage
mutation · secret key
returns SalesQuoteMessagePayload!
id: ID!
body: String!
Send the customer a message (emailed and shown on their quote page).
mutation NewQuote {
  createSalesQuote(input: {
    as: DRAFT
    customer: {email: "[email protected]", name: "Jordan Lee"}
    lines: [{variantId: "gid://shopify/ProductVariant/44001", title: "Party tent 6×12 m", quantity: 1, unitPrice: "1350.00"}]
    customerMessage: "Here is the price for your December event."
    send: true
  }) {
    salesQuote { id number status total }
    userErrors { code field message }
  }
}

SalesQuoteFilterInput

FieldTypeNotes
status[SalesQuoteStatus!]
searchStringNumber, customer name or email, product title or SKU.
sourceStringstorefront, cart, quick, admin, api, b2b_review, import.
customerIdID
updatedSinceStringOnly quotes changed at or after this moment (ISO 8601).

SalesQuoteCreateInput

FieldTypeNotes
asSalesQuoteCreateAs = DRAFT
customerSalesQuoteCustomerInput
lines[SalesQuoteLineInput!]
localeString
sendBooleanDRAFT only: send it at once.
customerMessageString
termsString
expiresAtStringY-m-d (end of that day in the store’s time zone) or ISO 8601.
discountSalesQuoteDiscountInput
shippingSalesQuoteShippingInput
tags[String!]

SalesQuoteCustomerInput

FieldTypeNotes
idIDThe Shopify customer (gid://shopify/Customer/… or the number), when there is one.
emailString
nameString
phoneString

SalesQuoteLineInput

FieldTypeNotes
variantIdIDA catalog variant (gid://shopify/ProductVariant/… or the number). Leave it out for a custom item.
productIdID
titleString!
variantTitleString
skuString
quantityInt!
listPriceStringThe catalog price (defaults to what the variant costs when the line comes from the storefront).
unitPriceStringYour price per unit. Empty = the list price. Required for a custom item.
requestedPriceString
discountSalesQuoteDiscountInput
taxableBoolean
requiresShippingBoolean
propertiesJSONLine properties (visible, and product-option data with keys starting with _).
noteString

SalesQuoteDiscountInput

FieldTypeNotes
typeSalesQuoteDiscountType!
valueString!A percentage (0–100) or an amount; FIXED on a line is per unit.
titleString

SalesQuoteShippingInput

FieldTypeNotes
titleString
priceString!

SalesQuoteUpdateInput

FieldTypeNotes
customerSalesQuoteCustomerInput
lines[SalesQuoteLineInput!]Replaces every line of the working version.
customerMessageString
termsString
expiresAtString
discountSalesQuoteDiscountInput
shippingSalesQuoteShippingInput
taxExemptBoolean
tags[String!]
EnumValues
SalesQuoteStatusNEW
IN_REVIEW
DRAFT
SENT
CHANGES_REQUESTED
ACCEPTED
ORDERED
EXPIRED
DECLINED
REJECTED
CANCELLED
SalesQuoteCreateAsDRAFT
REQUEST
SalesQuoteDiscountTypePERCENT
FIXED
SalesQuoteConvertModeINVOICE
ORDER
TypeFields
SalesQuote
A quote (the customer’s request and every version the store sent).
id: ID!, number: String!, publicId: String!, status: SalesQuoteStatus!, source: String!, customer: SalesQuoteCustomer!, total: String, currency: String, expiresAt: String, viewedAt: String, createdAt: String, updatedAt: String, draftOrderId: ID, orderId: ID, orderName: String, invoiceUrl: String, tags: [String!]!, answers: JSON, working: SalesQuoteVersion, sent: SalesQuoteVersion, request: SalesQuoteVersion, versions: [SalesQuoteVersionSummary!]!, notes: [SalesQuoteMessage!]!
SalesQuoteCustomerid: ID, name: String, email: String, phone: String
SalesQuoteVersionn: Int!, author: String!, locked: Boolean!, sentAt: String, currency: String, subtotal: String!, discountTotal: String!, shippingTotal: String!, taxTotal: String!, total: String!, taxesIncluded: Boolean!, customerMessage: String, terms: String, discount: JSON, shipping: JSON, lines: [SalesQuoteLine!]!
SalesQuoteLinevariantId: ID, productId: ID, title: String!, variantTitle: String, sku: String, custom: Boolean!, quantity: Int!, listPrice: String, requestedPrice: String, unitPrice: String, discount: JSON, lineTotal: String!, taxable: Boolean!, requiresShipping: Boolean!, properties: JSON, note: String
SalesQuoteVersionSummaryn: Int!, author: String!, locked: Boolean!, sentAt: String, total: String!, currency: String
SalesQuoteMessageid: ID!, author: String!, body: String!, internal: Boolean!, at: String
SalesQuotePayloadsalesQuote: SalesQuote, userErrors: [RentalUserError!]!
SalesQuoteConvertPayloadsalesQuote: SalesQuote, draftOrderId: ID, invoiceUrl: String, orderId: ID, orderName: String, userErrors: [RentalUserError!]!
SalesQuoteMessagePayloadmessage: SalesQuoteMessage, userErrors: [RentalUserError!]!