API: customers and orders
Customer API endpoints and data shapes for customers, addresses, shipping, orders, payment, and order tracking, in the order of the purchase flow
This page follows the second half of the purchase flow: after sign-in, the customer selects an address and shipping, creates the order, pays, and follows the order. All calls on this page need a customer token. For the procedure with examples, refer to Checkout and payment.
Customer profile
/customerThe signed-in customerCustomer/customerChange firstName, lastName, language, notificationPreferenceCustomer/customer-organisationThe customer's organisation, with its customers and addressesCustomer/customer-organisationChange name or languageCustomertype Customer = {
customerId: number
email: string | null
firstName: string | null
lastName: string | null
phoneNumber: string | null
organisationName: string | null
language: string
notificationPreference: 'EMAIL' | 'SMS' | 'WHATSAPP'
customerType: 'PRO_FORMA' | 'ACCOUNT' | 'INTERNAL'
discountPercentage: number | null
}Customer types
customerType controls the payment methods. Refer to Choose the payment methods.
| Type | Meaning |
|---|---|
PRO_FORMA | Pays before production (the default) |
ACCOUNT | Can always pay by invoice or by purchase order |
INTERNAL | An internal customer of the manufacturer. No online payment. |
Addresses
/addressList the addresses of the organisationCustomer/address/{addressId}Get one addressCustomer/addressCreate an addressCustomer/address/{addressId}Delete an address. 204.CustomerThere is no call to change an address. Create a new one.
type Address = {
addressId: number // omit when you create an address
name: string // name of the contact person
company: string
street1: string
street2: string
city: string
state: string
zip: string
country: string // the "country" value from GET /countries
jurisdictionIsoCode: string // the "iso" value from GET /countries/{country}/jurisdictions
phone: string
email: string
residential: boolean
taxId: string | null
isBillingAddress: boolean
isShippingAddress: boolean
countryAlpha2Code: string // response only
countryAlpha3Code: string // response only
}Send all fields when you create an address. Use an empty string for text fields that the customer leaves empty.
For the country and jurisdiction lists, refer to Store settings.
Shipping
For the shipping methods of the store, refer to List shipping methods. For the shipping object of an order, refer to CreateShipping in Get a price.
Get shipping rates
/shipping/rateCustomer// Request
{
currency: string
toAddressId: number
parts: { partRevisionId: string; units: MeasurementUnit; quantity: number; processPricesId: string; materialId: number }[]
}
// Response
type ShippingRates = {
shippingMethodId: number | null
tooLargeForBoxes: boolean // the parts do not fit the boxes of the manufacturer
errorWithCarrier: boolean // the carrier gave no rate
rates: { id: string; rate: number; currency: string; serviceType: string; serviceName: string; shippingMethodId: number }[]
}[]A rate id is the rateId of the shipping object. A rate belongs to the customer's organisation.
Orders
A quote and an order are one resource. state is QUOTE until the customer pays or accepts; then it is ORDER.
/orderCreate a quote / order. Body: CreateOrder.Customer/orderAll quotes and orders of the organisation, newest firstCustomer/order/{orderId}One orderCustomer/order/{orderId}/quotePrice breakdown (Quote). The keys of requisitions are requisition IDs.Customer/order/{orderId}/purchasabilityCan the order be paid now (Purchasability)Customer/requisition?orderId={orderId}The lines of an orderCustomer/order/{orderId}/shippingSet or replace the shipping. Body: CreateShipping.Customer/order/{orderId}/discount/{discountId}/applyApply a discount. 204.Customer/order/{orderId}/discount/removeRemove the discount. 204.Customer/order/{orderId}/requisitions/removeRemove lines. Body: { "requisitionIds": [1, 2] }.CustomerCreate an order
/orderCustomerThe body is CreateOrder, the same as POST /pre-order. For the rules, refer to Create the order.
Response:
{ order: Order; requisitionMapping: Record<string, Requisition> } // key: your line keyOrder data shapes
type Order = {
id: number
state: 'QUOTE' | 'ORDER'
quoteNumber: string | null
orderNumber: string | null // set when the quote becomes an order
price: number | null
currency: string
paymentStatus: 'UNPAID' | 'PROCESSING' | 'PAID' | 'REFUNDED' | 'EXTERNALLY_TRACKED'
isReviewRequired: boolean
isVoided: boolean
isArchived: boolean
operatorNote: string | null
purchaseOrderNumber: string | null
requisitionIds: number[]
threadId: number // for messages and files
shipping: Shipping | null
shipments: Shipment[]
billingAddress: Address | null
discount: { discountId: number; code: string | null; percentage: number } | null
tax: object | null
kanbanColumn: { id: string; name: string; color: string | null } | null // production stage
createdAt: string
lastUpdated: string
}
type Requisition = {
id: number
orderId: number
sequence: number
name: string
partRevisionId: string
units: MeasurementUnit
quantity: number
processPricesId: string
materialId: number
colorId: number | null
infillId: number | null
precisionId: number | null
leadTimeId: string | null
postProcessingIds: number[]
pricePaid: number | null
watertight: boolean
}
type Shipment = {
id: string
type: 'COURIER' | 'COLLECTION'
fulfilledAt: string
destination: object
parcels: object[]
tracking?: { provider: string; providerService: string; trackingNumber: string; trackingUrl: string | null } | null
}Shipping in a response is the CreateShipping object plus read-only fields such as rate, name, toAddress, and expectedDispatchDate.
Payment
For which methods to show and the procedure, refer to Checkout and payment.
/order/{orderId}/paymentStart an online paymentCustomerPATCH/order/{orderId}/payment/invoicePay by invoiceCustomerPATCH/order/{orderId}/payment/purchase-orderPay by purchase orderCustomerStart an online payment
/order/{orderId}/paymentCustomerNo body.
type Payment = {
id: string
provider: string // the paymentProvider of the store
finalPrice: number
tax: number
currency: string
clientSecret?: string | null
paymentPrincipal?: string | null
merchantAccount?: string | null
flywireGatewayUrl?: string | null
stripePaymentIntentStatus?: string | null
}| Provider | id | clientSecret | paymentPrincipal | merchantAccount |
|---|---|---|---|---|
STRIPE | Payment intent ID | Payment intent client secret | - | Connected account ID of the store |
PAYPAL | PayPal order ID | - | PayPal order ID | Merchant ID of the store |
RAZORPAY_SINGLE_PARTY | Razorpay order ID | - | Razorpay order ID | Razorpay key ID |
FLYWIRE | - | - | - | - (open flywireGatewayUrl) |
Errors: 404 ORDER_NOT_FOUND; 400 INTERNAL_ORDER_NOT_PAYABLE; 400 ORDER_ERROR (also when the order cannot be paid).
After the customer completes the payment with the provider, poll GET /order/{orderId} until paymentStatus changes.
To complete a Stripe or PayPal payment in your storefront, you need the Phasio platform key for the provider SDK. Contact Phasio support to get it.
Pay by invoice
/order/{orderId}/payment/invoiceCustomerNo body. Returns the Order. 400 with an empty body if the method is not permitted.
Pay by purchase order
/order/{orderId}/payment/purchase-orderCustomermultipart/form-data with optional fields purchaseOrderNumber, message, and file. Returns the Order. 400 with an empty body if the method is not permitted.
Documents
/document/order/{orderId}/estimateQuote PDFCustomer/document/order/{orderId}/confirmationOrder confirmation PDFCustomer/document/order/{orderId}/invoiceInvoice PDF. 403 if isInvoiceDownloadEnabled is false. 404 if there is no invoice.CustomerMessages and files
Each order has a thread (Order.threadId).
/activity/thread/{threadId}Messages and events of the thread, oldest firstCustomer/activitySend a messageCustomer/thread-file/thread/{threadId}List the files of the threadCustomer/thread-file/thread/{threadId}?name={name}Upload a file (multipart/form-data, field file)Customer/thread-file/thread/{threadId}/{fileId}Download a fileCustomerSend a message:
{ "activityType": "CONVERSATION", "conversationType": "GENERIC", "threadId": 880, "message": "When will you ship?" }Projects
A project groups orders and files for a customer.
/project?page=0&size=20&sort=createdAt,desc&status=ACTIVEList projects (in pages)Customer/project/{projectId}Get a projectCustomer/projectCreate a project: { "name": "…", "description": "…", "status": "ACTIVE" }Customer/order/project/{projectId}Orders of a projectCustomerPage response:
type Page<T> = { content: T[]; totalElements: number; totalPages: number; pageNumber: number; pageSize: number; isEmpty: boolean; isFirst: boolean; isLast: boolean }Catalog
A catalog contains parts with agreed prices for one customer organisation.
/catalogThe catalog of the organisation: { parts: CatalogItem[] }Customer/catalog/{catalogItemId}/part-revisionPart dataCustomer/catalog/{catalogItemId}/thumbnailPNG imageCustomerLast updated on