# Orders

## Create an order

{% hint style="warning" %}
Orders with the same `tenantOrderId` are only allowed if the previous orders are **not** in the status OPEN, LOCKED, or PROMISED. Cancel the previous orders first.
{% endhint %}

To create a new order at fulfillmenttools, call the following POST endpoint:

```http
POST https://{projectId}.api.fulfillmenttools.com/api/orders
```

```json
{
  "consumer": {
    "addresses": [
      {
        "salutation": "Meneer",
        "firstName": "David",
        "lastName": "van den Boomgaard",
        "street": "Rombout Hogerbeetsstraat",
        "houseNumber": "96",
        "postalCode": "1052 XM",
        "province": "Noord-Holland",
        "city": "Amsterdam",
        "country": "NL"
      }
    ],
    "email": "david.boomgaard@mail.nl"
  },
  "tenantOrderId": "R456728546",
  "orderDate": "2024-01-19T08:45:50.525Z",
  "orderLineItems": [
    {
      "article": {
        "tenantArticleId": "TSHIRT-W-2468",
        "title": "Basic T-Shirt White"
      },
      "quantity": 10
    },
    {
      "article": {
        "tenantArticleId": "JEANS-B-2605",
        "title": "Washed Slim Fit Jeans"
      },
      "quantity": 3
    },
    {
      "article": {
        "tenantArticleId": "SNEAK-W-4891",
        "title": "White Sneakers"
      },
      "quantity": 1
    }
  ],
  "deliveryPreferences": {
    "shipping": {
      "serviceLevel": "DELIVERY"
    }
  }
}
```

If the request was successful, it returns an HTTP `200 OK` response with a body that contains some new values:

`id`: Every order has a unique generated ID for identification

`version`: Version as part of our optimistic locking mechanism

`orderLineItems[].id`: Each order line item has its ID

`status`: Every order has a status, newly posted orders always have the status `OPEN`

`processId`: A process is an entity containing every entity involved in the whole fulfilling process

`created`: Time at which the order was created in the platform

`lastModified`: Time the order was most recently modified

## Modify an order

Not all properties of an order can be modified after the order has been placed. The following properties can be changed:

* **Order line items**
  * Modify quantity and article properties (except `tenantArticleId`)
  * Add new line items or remove existing ones
  * Feature must be activated in [order modification configuration](#order-modification-configuration)
  * See [Order Line Items Modification](#order-line-items-modification) for details
* **Order custom attributes**
  * Can only be modified before pick job or handover job has started
* **Preferred handling time**
  * Shipping orders: Updates `desiredDeliveryTime`
  * Click-and-Collect orders: Updates `provisioningTime`
  * Can only be modified before pick job or handover job has started
* **Consumer details/addresses**
  * Generally modifiable at any time
  * Changes to delivery addresses (`POSTAL_ADDRESS` or `PARCEL_LOCKER`) only allowed before handover job has started
  * See [Modification Restrictions](#modification-restrictions-based-on-process-state) for details

To modify an existing order at fulfillmenttools, call the following PATCH endpoint:

```http
PATCH https://{projectId}.api.fulfillmenttools.com/api/orders/{orderId}
```

The request body can contain any combination of the modifiable properties:

```json
{
  "version": 1,
  "comment": "Customer requested address correction and item updates",
  "customAttributes": {
    "customerSpecialHandling": "voucher",
    "internalNote": "VIP customer"
  },
  "orderLineItems": [
    {
      "id": "existing-orderlineitem-id",
      "quantity": 5,
      "article": {
        "title": "Updated Product Title",
        "imageUrl": "https://example.com/updated-image.jpg"
      }
    },
    {
      "quantity": 2,
      "article": {
        "tenantArticleId": "5020064",
        "title": "Wandtattoo Stadion",
        "imageUrl": "https://d358g9injarr4u.cloudfront.net/res/product_1000/343f4569-66bb-4b0c-aa2b-20011a51b620.jpg",
        "attributes": [
          {
            "category": "descriptive",
            "priority": 100,
            "key": "Maße",
            "value": "70 x 50 cm"
          },
          {
            "category": "descriptive",
            "priority": 200,
            "key": "Beschreibung",
            "value": "Wandtattoo in Ziegelwand-Optik, Mit tollem Blick aufs Stadion"
          }
        ]
      }
    }
  ],
  "addresses": [
    {
      "salutation": "Herr",
      "personalTitle": "Dr.",
      "firstName": "Max",
      "lastName": "Mustermann",
      "street": "Musterstraße",
      "houseNumber": "123",
      "postalCode": "50667",
      "city": "Köln",
      "country": "DE",
      "province": "DE-NW",
      "phoneNumbers": [
        {
          "value": "+49123456789",
          "label": "private",
          "type": "MOBILE"
        }
      ],
      "additionalAddressInfo": "2. Stock, links",
      "email": "max.mustermann@example.com",
      "addressType": "POSTAL_ADDRESS",
      "coordinates": {
        "lat": 50.9375,
        "lon": 6.9603
      }
    }
  ],
  "preferredHandlingTime": "2027-05-04T13:00:00.000Z"
}
```

### Order line items modification

Order line items can be modified in three ways:

1. **Update existing item**: Provide the `id` of the order line item
   * You can change the `quantity`
   * You can modify article properties (for example, `title`, `imageUrl`, `attributes`)
   * The `tenantArticleId` can't be modified
2. **Add new item**: Omit the `id` field
   * Provide complete `article` object with `tenantArticleId`
   * Specify desired `quantity`
   * Article `attributes` are optional
   * Same validation rules as order creation apply
3. **Remove item**: Set `quantity` to `0` for an existing order line item
   * At least one order line item must remain in the order

{% hint style="warning" %}
The `orderLineItems` array works as a diff/patch:

* Only include the order line items you want to change or add
* Order line items not included in the request remain unchanged
* Duplicate `tenantArticleId` values aren't supported
  {% endhint %}

**Example:**

```json
"orderLineItems": [
  {
    "id": "existing-item-id",
    "quantity": 5,
    "article": {
      "title": "Updated Product Title",
      "imageUrl": "https://new-image-url.com/image.jpg"
    }
  },
  {
    "quantity": 2,
    "article": {
      "tenantArticleId": "NEW-ARTICLE-123",
      "title": "New Product",
      "attributes": [
        {
          "category": "descriptive",
          "key": "Color",
          "value": "Blue"
        }
      ]
    }
  },
  {
    "id": "remove-this-item-id",
    "quantity": 0
  }
]
```

### Modification restrictions based on process state

Not all order properties can be modified at all times. Depending on the fulfillment process state, certain modifications are restricted:

#### Consumer/addresses

**Generally modifiable at any time**, except:

* Changes to delivery addresses (addresses with `addressType: POSTAL_ADDRESS` or `addressType: PARCEL_LOCKER`)
* Changes to `facilityRef`
* Changes to `tenantFacilityId`

These modifications are only allowed before a handover job has started.

#### Custom attributes

Can only be modified when no pick job has started and no handover job has started.

#### Preferred handling time

The `preferredHandlingTime` field updates different properties depending on the order type:

* **Shipping orders**: Updates `desiredDeliveryTime` in `deliveryPreferences.shipping`
* **Click-and-Collect orders**: Updates `provisioningTime` in the facility preferences

Can only be modified when no pick job has started and no handover job has started.

#### Order line items

Requires the order modification configuration flag `allowOrderLineItemModification` to be set to `true`.

See [Order modification configuration](#order-modification-configuration) for more information.

{% hint style="info" %}
There's no automated way to query the pick job or handover job status before attempting a modification. Consider the timing of your modifications and handle potential errors appropriately.
{% endhint %}

### Response

If the request was successful, it returns an HTTP `200 OK` response with a body containing the updated order.

Be aware that:

* An order must have at least one order line item with a quantity > 0.
* All validations that are applied during order creation are also applied during order modification.
* **Rerouting behavior**:
  * Modifications to `orderLineItems`, `customAttributes`, or `preferredHandlingTime` trigger automatic rerouting of the order.
  * Modifications to consumer details or addresses don't trigger rerouting.
* You can provide a `comment` for the modification, which is part of new `updateDetails` field in the order.
* The user field is only set when the `actorAnonymization` in the [GPDR configuration](https://docs.fulfillmenttools.com/documentation/by-pillar/order-management/gdpr-configuration) is set to `false`.
* An event is sent when an order is modified. See [Available events](https://docs.fulfillmenttools.com/documentation/getting-started/eventing/available-events) for more information.
* Modification restrictions depend on the fulfillment process state (pick job, handover job). See [Modification Restrictions](#modification-restrictions-based-on-process-state) above.
* The `orderLineItems` array works as a diff. Only include items you want to modify, add, or remove. Other items remain unchanged.
* Duplicate `tenantArticleId` values within a single order aren't supported.
* To remove an order line item, set its `quantity` to `0`.
* The `tenantArticleId` of an existing order line item can't be changed.

```json
{
  // ...order body
  "updateDetails": [
    {
      "created": "2024-05-01T10:15:30.000Z",
      "user": "customer-service@fulfillmenttools.com",
      "comment": "Customer requested address correction and item updates",
      "changes": {
        "customAttributes": {
          "customerSpecialHandling": "voucher",
          "internalNote": "VIP customer"
        },
        "preferredHandlingTime": "2027-05-04T13:00:00.000Z",
        "orderLineItems": [
          {
            "id": "75d37a56-8e97-4598-afe9-4523af32bc0c",
            "quantity": 5
          }
        ],
        "addresses": [
          {
            "street": "Musterstraße",
            "houseNumber": "123",
            "postalCode": "50667",
            "city": "Köln",
            "country": "DE",
            "addressType": "POSTAL_ADDRESS"
          }
        ]
      }
    }
  ]
}
```

## Order modification configuration

There's an order modification configuration that controls the behavior of the order modification feature.

Currently supported:

* Enabling or disabling the modification of order line items

```http
PUT https://{projectId}.api.fulfillmenttools.com/api/configurations/ordermodification
```

```json
{
  "version": 1,
  "allowOrderLineItemModification": true
}
```

## Authorization for order modification

Different order modification operations require specific permissions:

### Required permissions

* **ORDER\_WRITE**: Required for all order modifications
* **ORDER\_CONSUMER\_WRITE**: Additionally required when modifying consumer details or addresses
* **ORDER\_LINEITEM\_WRITE**: Additionally required when modifying order line items

### Permission examples

**Modifying only custom attributes or preferred handling time:**

```
Required: ORDER_WRITE
```

**Modifying addresses:**

```
Required: ORDER_WRITE + ORDER_CONSUMER_WRITE
```

**Modifying order line items:**

```
Required: ORDER_WRITE + ORDER_LINEITEM_WRITE
```

**Modifying multiple properties (for example, addresses and line items):**

```
Required: ORDER_WRITE + ORDER_CONSUMER_WRITE + ORDER_LINEITEM_WRITE
```

See the [Authorization article](https://docs.fulfillmenttools.com/documentation/getting-started/authentication-and-authorization) for more information.

## Order modification error handling

### Optimistic locking conflicts

If the order has been modified by another process since you last retrieved it, you'll receive a `409 Conflict` error. In this case:

1. Fetch the latest version of the order
2. Review the changes
3. Retry your modification with the updated `version` number

### Validation errors

All validations from order creation also apply to modifications:

* At least one order line item must remain (quantity > 0)
* Duplicate `tenantArticleId` values aren't allowed
* All required fields must be present and valid

### Process state restrictions

If you attempt a modification that is not allowed in the current process state (for example, changing the delivery address after handover has started), you'll receive an error response. Since there's no automated way to query the process state beforehand, handle these errors appropriately in your integration.

## Best practices for order modification

1. **Always include the current version**: Use optimistic locking to prevent conflicts.
2. **Provide meaningful comments**: Help track the reason for modifications in the `updateDetails` history.
3. **Use diff-based updates for line items**: Only include changed items in `orderLineItems` array to keep the request minimal.
4. **Be aware of process state timing**: Consider the timing of your modifications relative to the fulfillment process.
5. **Understand re-routing behavior**: Modifications to order line items, custom attributes, or preferred handling time trigger automatic re-routing. Consumer/address updates do not trigger re-routing.
6. **Monitor events**: Listen to `ORD`
