View as Markdown

Orders

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


POST /v1/orders

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

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

Per-order shape

{
  "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

FieldNotes
order_idNatural key, unique per shop
placed_atRFC3339 with explicit offset (bare local rejected)
currencyISO-4217 alpha-3
statuspaid | pending | voided
line_items1-500; each needs line_id, quantity, unit_price
totalWhat 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:

{
  "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).