DUMA/ API

Create an order

Records a checkout from your website. DUMA prices it from the products you name, matches or creates the customer by email, keeps the address and takes the stock off at once.

POSThttps://api.duma-business.com/v1/store/orders

orders:writeSecret key only

Idempotent by externalReference: the same reference with the same shopper and lines returns the original order with status 200 and replayed: true; with a different basket it is 409 idempotency_conflict.

A size that has run out fails the whole order with 409 out_of_stock and an items list of what was short. Nothing is recorded.

If expectedTotal disagrees with DUMA’s total the answer is 409 total_mismatch, carrying total, items, deliveryFee and discount.

A pending order holds its stock and promo code until expiresAt; unclaimed by then, it expires and gives both back.

A promo code that cannot be used is a 400 promo_invalid; one used up as the order was placed is 409 promo_unavailable.

Request example

Example request
curl -X POST "https://api.duma-business.com/v1/store/orders" \
  -H "Authorization: Bearer dk_sec_…" \
  -H "Content-Type: application/json" \
  -d '{
  "externalReference": "WEB-10482",
  "customer": {
    "email": "[email protected]",
    "firstName": "Amelia",
    "lastName": "Hart",
    "phone": "07700 900123",
    "marketingOptIn": true
  },
  "items": [
    {
      "variantId": "3d7e9b1a-6c4f-4e2d-b8a5-9f0c1e2d3a4b",
      "quantity": 2
    }
  ],
  "fulfilment": {
    "type": "shipping",
    "method": "Royal Mail Tracked 48",
    "fee": "4.95",
    "address": {
      "recipientName": "Amelia Hart",
      "phone": "07700 900123",
      "line1": "14 Elm Grove",
      "city": "Bristol",
      "postcode": "BS6 6AH",
      "country": "GB"
    }
  },
  "payment": {
    "provider": "stripe",
    "reference": "pi_3PqR8sLkdIwHu7ix0abc1234",
    "method": "card",
    "status": "paid"
  },
  "expectedTotal": "100.95"
}'

Request body

JSON, sent with Content-Type: application/json.

externalReferencestringRequired
Your own order number, up to 120 characters. Sending it again returns the same order.
customerobjectRequired
The shopper. Matched to an existing customer by email, or created.
customer.emailstringRequired
Lower-cased for you. Up to 255 characters.
customer.firstNamestringRequired
Up to 100 characters.
itemsarrayRequired
The basket, 1 to 100 lines. Name each line’s product with productId, variantId or sku — prices always come from DUMA.
items[].quantitynumberRequired
A whole number from 1 to 999.
fulfilmentobjectRequired
How the order reaches the shopper.
fulfilment.typestringRequired
Shipping and delivery need an address; collection does not.
shippingdeliverycollection
fulfilment.address.recipientNamestringRequired
Up to 200 characters.
fulfilment.address.line1stringRequired
Up to 200 characters.
fulfilment.address.citystringRequired
Up to 120 characters.
fulfilment.address.postcodestringRequired
Up to 20 characters.
fulfilment.address.countrystringRequired
A two-letter country code, such as GB. Upper-cased for you.
paymentobjectRequired
Who took the money, and whether it has been taken.
payment.providerstringRequired
Who took the money, e.g. "stripe", "paypal". Up to 50 characters.

Optional

customer.lastNamestringDefault ""
Up to 100 characters.
customer.phonestring
Up to 30 characters.
customer.marketingOptInbooleanDefault false
The shopper ticked “email me news and offers” at checkout.
items[].productIdstring (uuid)
The product. A product that comes in sizes also needs variantId or sku.
items[].variantIdstring (uuid)
The size. On its own it names its product.
items[].skustring
The size by SKU, instead of variantId. Up to 100 characters.
items[].discountCodestring
Deprecated: a catalogue discount’s code for this line. Use promoCode instead.
fulfilment.methodstring
Your name for the service, e.g. “Royal Mail Tracked 48”. Up to 100 characters.
fulfilment.feestringDefault "0"
Delivery fee as a decimal string such as "4.95". Shipping and delivery only; collection is always free.
fulfilment.addressobject
Required for shipping and delivery.
fulfilment.address.phonestring
Up to 30 characters.
fulfilment.address.line2string
Up to 200 characters.
fulfilment.address.regionstring
Up to 120 characters.
payment.referencestring
Their reference for it — a payment intent or charge id.
payment.methodstringDefault "card"
Up to 50 characters.
payment.statusstringDefault paid
paid: your website took the money. pending: not paid yet (e.g. a bank transfer staff will check). claimed: the shopper says they have paid.
paidpendingclaimed
payment.expiresInMinutesnumberDefault 60
How long a pending order holds its stock and promo code unclaimed, 5–10080 minutes.
currencystring
The three-letter currency the shopper pays in; the workspace’s if omitted. Every line needs a price in it, or the request fails with 409 price_unavailable.
promoCodestring
A promo code for the whole order (promotions module). Case and spaces do not matter. Up to 60 characters.
expectedTotalstring
What your website charged, items plus delivery, as a decimal string. If DUMA’s total differs, nothing is recorded.
notesstring
Up to 1000 characters.

Response

Response · 201
{
  "data": {
    "id": "6b2d8f4a-1e3c-4a5b-9d7e-0f1a2b3c4d5e",
    "externalReference": "WEB-10482",
    "status": "pending",
    "paymentStatus": "paid",
    "payment": {
      "status": "paid",
      "provider": "stripe",
      "reference": "pi_3PqR8sLkdIwHu7ix0abc1234",
      "method": "card"
    },
    "expiresAt": null,
    "totals": {
      "items": "96.00",
      "deliveryFee": "4.95",
      "discount": "0.00",
      "tax": "16.00",
      "total": "100.95"
    },
    "currency": "GBP",
    "total": "100.95",
    "tax": "16.00",
    "deliveryFee": "4.95",
    "fulfilment": {
      "type": "shipping",
      "method": "Royal Mail Tracked 48",
      "address": {
        "recipientName": "Amelia Hart",
        "phone": "07700 900123",
        "line1": "14 Elm Grove",
        "line2": null,
        "city": "Bristol",
        "region": null,
        "postcode": "BS6 6AH",
        "country": "GB"
      }
    },
    "customerId": "9c1e3a5b-7d2f-4b6a-8e0c-1d3f5a7b9c2e",
    "items": [
      {
        "productId": "8f1c2a4e-3b6d-4c1e-9a7f-2d5b8e0c4a13",
        "variantId": "3d7e9b1a-6c4f-4e2d-b8a5-9f0c1e2d3a4b",
        "sku": "HOOD-BLK-M",
        "name": "Oversized Hoodie — M / Black",
        "quantity": 2,
        "unitPrice": "48.00",
        "subtotal": "96.00"
      }
    ],
    "createdAt": "2026-10-28T10:42:17.000Z"
  }
}