Create products and orders
Build a reliable product and order intake flow for ecommerce and fulfilment integrations.
Use the Organization API
Product catalogue and order intake belong to the Organization API. Your webshop or integration creates the commercial records there; PackCloud then allocates the resulting work to a warehouse.
https://api.pack.cloud/v1/organizations/{organizationId}/graphqlBuild the intake flow
Keep the PackCloud IDs returned by each mutation. An order line refers to a PackCloud product ID, so products must be synchronized before their first order arrives.
- Resolve the PackCloud brand ID for the webshop or sales channel.
- Create each sellable product variant and store its returned product ID.
- Create the order with at least one line and the recipient address.
- Check both top-level GraphQL errors and the mutation payload's user errors.
- Store the returned order and line IDs for later updates, holds, or cancellation.
Create a product
Create one PackCloud product for each sellable variant. Use a stable code from your ecommerce system, but keep your own mapping to the returned PackCloud ID: product codes are not unique.
nameis required by runtime validation.- When you add a barcode, send both
barcodeandquantity. - Barcode values must be distinct and cannot already belong to another active product.
- Send money amounts as decimal strings and currency codes as uppercase ISO 4217 codes.
mutation ProductCreate($input: ProductCreateInput!) {
productCreate(input: $input) {
product {
id
name
code
type
barcodes {
barcode
quantity
}
}
userErrors {
field
message
}
}
}{
"input": {
"name": "Canvas backpack – green",
"brandName": "Acme Outdoor",
"code": "BAG-CANVAS-GREEN",
"type": "STANDARD",
"barcodes": [
{
"barcode": "8712345678906",
"quantity": 1
}
],
"price": {
"currency": "EUR",
"value": "59.95"
},
"weight": {
"value": 750,
"unit": "G"
}
}
}{
"data": {
"productCreate": {
"product": {
"id": "cf695726-3f50-4aa0-b686-d45f55042bfa",
"name": "Canvas backpack – green",
"code": "BAG-CANVAS-GREEN",
"type": "STANDARD",
"barcodes": [
{
"barcode": "8712345678906",
"quantity": 1
}
]
},
"userErrors": []
}
}
}A successful result has an empty userErrors array and a non-null product.id. Persist that ID before accepting orders for the product.
Create an order
Replace the example brand and product UUIDs with IDs from the same organization. For delivery orders, include a recipient address. If billing details are omitted, PackCloud uses the recipient address as the billing address.
brandIdA brand in the selected organization.linesAt least one line with productId, quantityOrdered, and name.recipientAddressRequired for delivery; local pickup can omit it.referenceOptional external reference, limited to 25 characters and not unique.mutation OrderCreate($input: OrderCreateInput!) {
orderCreate(input: $input) {
order {
id
reference
status
lines(first: 10) {
edges {
node {
id
name
quantityOrdered
product {
id
}
}
}
}
}
userErrors {
field
message
}
}
}{
"input": {
"brandId": "f3c82a83-27e9-4e8f-8148-468bc65827c7",
"reference": "WEB-10482",
"recipientAddress": {
"name": "Alex de Vries",
"address": "Keizersgracht",
"houseNumber": "391 A",
"postalCode": "1016 EJ",
"city": "Amsterdam",
"countryCode": "NL",
"email": "alex@example.com"
},
"lines": [
{
"productId": "37aed8af-184d-4dc3-bf75-92db8fdcf3db",
"quantityOrdered": 2,
"name": "Canvas backpack – green",
"price": {
"currency": "EUR",
"value": "59.95"
}
}
]
}
}{
"data": {
"orderCreate": {
"order": {
"id": "8c76f46e-2149-49d4-b028-9e2d281bdb67",
"reference": "WEB-10482",
"status": "CREATED",
"lines": {
"edges": [
{
"node": {
"id": "a6acb575-aab8-4676-a2ce-2d7f1d88a0d1",
"name": "Canvas backpack – green",
"quantityOrdered": 2,
"product": {
"id": "37aed8af-184d-4dc3-bf75-92db8fdcf3db"
}
}
}
]
}
},
"userErrors": []
}
}
}strictValidation: false relaxes format checks, but the core name, street, city, and country fields remain required.Handle mutation results
A mutation can return HTTP 200 and still be unsuccessful. Treat the write as complete only when userErrors is empty and the expected object ID is present.
{
"data": {
"orderCreate": {
"order": null,
"userErrors": [
{
"field": ["input", "lines", "0", "productId"],
"message": "The selected product is invalid."
}
]
}
}
}The field path tells you which input failed. Also handle top-level errors for invalid GraphQL documents, authentication problems, and unexpected server errors.
Continue the order lifecycle
productUpdateSynchronize later catalogue, barcode, price, or customs changes.orderUpdateChange order details while the order is still updatable.orderCreateLineAdd a product line after order creation.orderLineUpdateChange a line quantity or description while fulfilment still permits it.orderHoldTemporarily block an updatable order and record a reason.orderReleaseHoldRelease an order that was placed on hold.orderValidateQueue validation; success means queued, not fully processed.orderCancelCancel an order that has not already shipped or been cancelled.userErrors instead of assuming an update is still allowed.Retry without creating duplicates
Neither create mutation accepts an idempotency key. Product codes and order references are also not unique. A blind retry after a timeout can therefore create a duplicate.
- Record a local pending write against your ecommerce product or order ID.
- Send the create mutation once.
- Persist the PackCloud ID as soon as it is returned.
- After an ambiguous timeout, reconcile by your mapping and code or reference before retrying.
Use productUpdate or orderUpdate once you have a PackCloud ID. Do not use another create mutation to synchronize a known record.