GraphQL API
Organization API
Organization guide

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}/graphql

Build 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.

  1. Resolve the PackCloud brand ID for the webshop or sales channel.
  2. Create each sellable product variant and store its returned product ID.
  3. Create the order with at least one line and the recipient address.
  4. Check both top-level GraphQL errors and the mutation payload's user errors.
  5. 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.

  • name is required by runtime validation.
  • When you add a barcode, send both barcode and quantity.
  • 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.
productCreateOpen reference →
mutation ProductCreate($input: ProductCreateInput!) {
  productCreate(input: $input) {
    product {
      id
      name
      code
      type
      barcodes {
        barcode
        quantity
      }
    }
    userErrors {
      field
      message
    }
  }
}
Variables
{
  "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"
    }
  }
}
Response
{
  "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
    }
  }
}
Variables
{
  "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"
        }
      }
    ]
  }
}
Response
{
  "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": []
    }
  }
}
Address format checks are strict by default. PackCloud validates country-specific postal codes, email, phone, state code, and VAT formats when supplied. Setting 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

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.

  1. Record a local pending write against your ecommerce product or order ID.
  2. Send the create mutation once.
  3. Persist the PackCloud ID as soon as it is returned.
  4. 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.