Raw schema
{
"type": "object",
"properties": {
"product": {
"type": "string"
},
"size": {
"type": "string"
},
"quantity": {
"type": "number"
},
"options": {
"type": "object",
"description": "FULL selected options (same shape as vivid_price.options). Use vivid_product to see them. Prefer this over `size` for option-rich products."
},
"items": {
"type": "array",
"description": "For a MULTI-LINE order (e.g. two banners with DIFFERENT designs): one entry per line, each { product, size?, options?, quantity?, artwork? }. Different designs must be SEPARATE entries (quantity 1 each) with their OWN artwork. If provided, this replaces the single top-level product; contact/delivery/PO stay at the top level.",
"items": {
"type": "object",
"properties": {
"product": {
"type": "string"
},
"size": {
"type": "string"
},
"quantity": {
"type": "number"
},
"options": {
"type": "object"
},
"artwork": {
"type": "object",
"description": "THIS line's artwork { mode:'ai_design'|'upload_file'|'design_brief', ... } (same shape as top-level artwork)."
}
}
}
},
"name": {
"type": "string"
},
"email": {
"type": "string"
},
"company": {
"type": "string"
},
"phone": {
"type": "string"
},
"customerType": {
"type": "string",
"description": "retail|corporate|school|government|account β sets payment terms"
},
"delivery": {
"type": "object",
"description": "pickup or delivery details. PICKUP: { method:'pickup', name, email, phone, pickupLocation?, notes? }. DELIVERY: { method:'delivery', name, email, phone, company?, address1, address2?, suburb, state, postcode, country, notes? }. Contact (name/email/phone) can live here or at the top level. Omit entirely to keep the old behaviour."
},
"artwork": {
"type": "object",
"description": "{ mode:'ai_design'|'upload_file'|'design_brief', designId?, imageUrl?, printPdfUrl?, fileUrl?, brief? }"
},
"poNumber": {
"type": "string"
},
"confirm": {
"type": "boolean",
"description": "set true ONLY after the customer reviews and confirms"
}
},
"required": [
"email"
]
}