# Update or cancel an order

Read an order's current state, amend its amount or addresses before capture, attach your own references, acknowledge a Checkout order and cancel one you can't fulfill.

Everything on this page acts on an order that already exists, and most of it only works
*before* the order is captured. Read first, change second: the order's `status` and its
amount fields decide which of these calls will be accepted. You need an `order_id` and a
credential for the environment the order lives in.

## Before you start

Paths are relative to your [base URL](/api/authentication/#base-urls):
`https://api.playground.kustom.co/` while testing, `https://api.kustom.co/` in production.

**Send a `Kustom-Idempotency-Key` on every write.** Every `POST` and `PATCH` to Order Management moves money or changes the order. Send a `Kustom-Idempotency-Key` header with one UUID per operation, and reuse it when you retry, so a call repeated after a timeout runs once instead of twice. [Idempotency and retries](/order-management/idempotency-and-retries/) has the rules and the retry schedule.

Read the order before changing it. Every failure below is really the same failure: the
order wasn't in a state that allows the change, and the order body is what tells you that.

## Step by step

**1. Read the order.**

```http
GET /ordermanagement/v1/orders/{order_id}
```

```json
{
  "order_id": "7849fd84-47dc-4919-a7ce-xxxxxxxxxx",
  "status": "CAPTURED",
  "fraud_status": "ACCEPTED",
  "order_amount": 200,
  "original_order_amount": 200,
  "captured_amount": 200,
  "refunded_amount": 0,
  "remaining_authorized_amount": 0,
  "purchase_currency": "PLN"
}
```

Four amounts, and they're the whole state machine. `original_order_amount` is what was
authorized at checkout. `order_amount` is what it is now, after any amendment.
`captured_amount` and `refunded_amount` are what has actually moved.
`remaining_authorized_amount` is what you can still capture. When a call is refused, this
is the object that explains why.

**2. Change the amount, before capture.** Lower the total when the customer drops a line, or
when you can't fulfill part of the order.

```http
PATCH /ordermanagement/v1/orders/{order_id}/authorization
Kustom-Idempotency-Key: f06ebd62-6fc5-4021-a263-ef2c089974fa
```

```json
{
  "order_amount": 6000,
  "description": "One line out of stock",
  "order_lines": [
    {
      "type": "physical",
      "reference": "123050",
      "name": "Tomatoes",
      "quantity": 10,
      "quantity_unit": "kg",
      "unit_price": 600,
      "tax_rate": 0,
      "total_amount": 6000,
      "total_tax_amount": 0
    }
  ]
}
```

Only possible while the order is uncaptured, uncancelled and unexpired.

**3. Attach your own references,** so the order is findable by your order number rather
than only by Kustom's id.

```http
PATCH /ordermanagement/v1/orders/{order_id}/merchant-references
Kustom-Idempotency-Key: a01177d1-eb7d-4f37-a85b-b91da4bf8f31
```

```json
{
  "merchant_reference1": "15632423",
  "merchant_reference2": "special order"
}
```

**4. Correct the shipping address.**

```http
PATCH /ordermanagement/v1/orders/{order_id}/customer-details
Kustom-Idempotency-Key: c0b10c59-4d45-4b22-ab6c-0988762d5999
```

```json
{
  "shipping_address": {
    "street_address": "123 Fake St",
    "postal_code": "12345",
    "city": "New York",
    "region": "NY",
    "country": "US"
  }
}
```

The billing address isn't yours to change: the call takes only `shipping_address`, and the
change can still be refused depending on the order's state and its risk assessment.

**5. Acknowledge a Checkout order.** Tells Kustom you've taken responsibility for the
order and created it in your own system. Do this when you handle the push callback.

```http
POST /ordermanagement/v1/orders/{order_id}/acknowledge
Kustom-Idempotency-Key: 589d9d83-6abf-4f69-90f0-608765a84f58
```

**6. Cancel what you can't fulfill.** Releases the authorization and returns the reserved
money to the customer.

```http
POST /ordermanagement/v1/orders/{order_id}/cancel
Kustom-Idempotency-Key: 60cceee2-7d9b-4837-9870-7734a8e767cd
```

Only an uncaptured order can be cancelled. Once any part is captured, the way back is a
refund, not a cancellation.

After any change, re-read the order with step 1 and check the field you meant to change. For a cancel,
`status` moves away from an authorized state. For an amount change, `order_amount` moves
while `original_order_amount` stays where it was — which is exactly how you tell an
amended order from a fresh one.

## Troubleshooting

Every error carries an `error_code`, human-readable `error_messages` and a
`correlation_id`. Act on the code, and quote the correlation id to support.

| `error_code` | What it means |
|---|---|
| `UPDATE_NOT_ALLOWED` | The order's state or risk assessment doesn't allow changing its amount or address — read it and look at `status` |
| `NOT_ALLOWED` | The order isn't in a state that permits this change — read it and look at `status` |
| `NO_SUCH_ORDER` | The `order_id` doesn't exist, or belongs to the other environment |
| `CANCEL_NOT_ALLOWED` | The order has captures, so it can only be refunded |

All four describe where the order *is*, not what you sent, so retrying an unchanged request
fails identically. The [error catalogue](/api/errors/#errors-order-management) shows each one against
the lifecycle, with the status the call needs.

Only ever branch on `error_code`. The `error_messages` array is English, aimed at a
developer reading a log, and isn't stable enough to parse or safe to show a customer.

## Related

- [Capture an order](/order-management/capture/) — take the money
- [Refund an order](/order-management/refunds/) — give it back
- [Order Management](/order-management/) — why these calls exist
- [Order Management API reference](/api/order-management/) — the generated specification
