{/* Metadata lives in ./layout.tsx */}

# Orders

Push orders (line items, discounts, shipping, taxes, refunds) into Pluto. Same profit fidelity as Shopify when you supply the full picture. {{ className: 'lead' }}

<Warning>
  Not live yet. Wire contract below is the intended v1 surface.
</Warning>

---

## `POST /v1/orders`

**Scope:** `orders:write`. **Auth:** `Authorization: Bearer sk_plp_...`

Body: `{ "orders": [ ... ] }`, **1-250** items, body at most **4 MB**.

### Per-order shape

```json
{
  "order_id": "10052",
  "order_name": "#10052",
  "placed_at": "2026-07-12T14:03:22+02:00",
  "updated_at": "2026-07-13T09:00:00Z",
  "currency": "DKK",
  "status": "paid",
  "is_test": false,
  "customer": { "id": "cust_8842" },
  "line_items": [
    {
      "line_id": "1",
      "sku": "MUG-BLUE",
      "quantity": "2",
      "unit_price": "149.50",
      "line_discount": "0",
      "unit_cost": "41.20",
      "product_id": "88",
      "title": "Blue Mug"
    }
  ],
  "discounts": "20.00",
  "shipping": "39.00",
  "tax": "0",
  "taxes_included": true,
  "tips": "0",
  "duties": "0",
  "rounding_adjustment": "0",
  "total": "318.00",
  "payment_gateway": "stripe",
  "gateway_fee": "11.83",
  "subscription_id": null,
  "refunds": [
    {
      "refund_id": "10052-r1",
      "refunded_at": "2026-07-14T10:00:00+02:00",
      "total": "169.50",
      "tax_refund": "0",
      "shipping_refund": "0",
      "gateway_fee_refund": "0",
      "gift_card_refund": "0",
      "store_credit": false,
      "line_items": [{ "line_id": "1", "quantity": "1", "restock": true }]
    }
  ],
  "deleted": false
}
```

### Required fields

| Field | Notes |
| --- | --- |
| `order_id` | Natural key, unique per shop |
| `placed_at` | RFC3339 **with** explicit offset (bare local rejected) |
| `currency` | ISO-4217 alpha-3 |
| `status` | `paid` \| `pending` \| `voided` |
| `line_items` | 1-500; each needs `line_id`, `quantity`, `unit_price` |
| `total` | What the customer paid: the **original** total, never net of refunds |

### Sum identity

Exact equality (no silent tolerance):

```
sum(unit_price * qty) - sum(line_discount) - discounts
  + shipping + tips + duties + rounding_adjustment
  + (taxes_included ? 0 : tax)
  = total
```

A mismatch returns a per-item `sum_mismatch` with computed vs supplied.

### Idempotency

Natural-key upsert on `order_id`. Client `updated_at` (defaults to `placed_at`) drives the stale guard:

- **newer**: applied
- **equal**: accepted (idempotent re-send / replay)
- **older**: outcome `superseded` (no-op)

Re-send the **whole** order including full `refunds[]` history. Children omitted from a re-send are tombstoned.

### Gateway fees

Optional `gateway_fee` is an **actual**. When supplied it suppresses the fee-rule estimate for that order only. Without it, a matching `payment_gateway` may receive a rule-based estimate at read time.

### Customer id (PII policy)

`customer.id` must be **opaque**: no `@`, no spaces, at most 128 chars. Emails/phones are rejected (`pii_rejected`). Hash contact identifiers client-side if needed.

### Response

`200` with per-item results:

```json
{
  "accepted": 1,
  "rejected": 0,
  "superseded": 0,
  "results": [
    { "order_id": "10052", "outcome": "accepted" }
  ]
}
```

Outcomes: `accepted` | `rejected` | `superseded`. Rejected items include `errors: [{ code, message, field? }]`.

---

## `PUT /v1/source` and `GET /v1/source`

Register the source before the first order push: platform label, shop currency, IANA timezone. Currency/timezone become immutable after the first accepted order (`source_locked`).
