POST
Open a claim against an order

Authorizations

Authorization
string
header
required

A secret API key. Publishable keys cannot reach this API. A key may carry an expiry, and an expired key is refused exactly like an unknown one, with a 401 that names no reason; check the key's expires_at in the dashboard rather than inferring it from a response. When a merchant rolls a key's secret they choose a grace window of up to 3 days, and for its duration BOTH the new secret and the one it replaced authenticate, so an integration moves over on its own deploy schedule instead of at the instant the button is pressed. Move before the window closes: after it, the old secret is refused. Nothing else about this contract moves with a roll. The key keeps its id and its scopes, so the only thing an integration updates is the credential itself.

Headers

Idempotency-Key
string
required

A unique key per logical write. Replaying a request with the same key returns the first response byte for byte instead of applying the write twice.

Body

application/json

Opens a claim against a placed order. It lands as 'requested', exactly like one a shopper raised, so a merchant still approves it: a key that could open an already-approved claim would be the approval gate defeated by the create route, and on this family approval is the step before money moves. customer_initiated is recorded false, because a key is the merchant's own integration rather than the shopper, and no acting person is recorded at all. THE SETTLEMENT FIGURE IS COMPUTED HERE AND IS NEVER YOURS TO SEND. It is the claimed lines valued at what the shopper actually paid per unit, an integer in the MINOR UNITS of the order's currency, then scaled down in proportion to the order's own discounts, gift cards, store credit and loyalty. refund_amount and refund_amount_minor are refused by name, and the claim resource publishes no money and no currency at all, so what a later resolve actually paid is read from the order under read_orders rather than from here. THE STORE'S CLAIM WINDOW IS NOT APPLIED. That policy governs the storefront door, where a shopper raises a claim on their own order; a claim opened with an api key may name an order older than the window. THERE IS NO CONVERGENCE GUARANTEE OUTSIDE THE IDEMPOTENCY WINDOW. A claim has no unique column, so the same body replayed later opens a SECOND claim over the same lines, or answers 409 quantity_exceeds_ordered once the first has consumed them. Reconcile by listing GET /api/v1/order-claims?order_id=, not by re-posting. An order_id naming no order in this store answers 404 not_found rather than 400, even though it is a body field. NO FIELD HERE MAY BE SENT AS null. The nullable set on this body is empty, so an explicit null answers 400 naming the field; omit the key instead. ALSO REFUSED BY NAME: reason and items[].note, because that column carries the shopper's own words through one door and merchant prose about that shopper through the other and the read publishes neither, so text sent here could never be read back through any route; no_notification, because whether the shopper is emailed is a staff decision made where the person making it can see the customer, and a claim opened here notifies on every transition; status and customer_initiated, because the platform sets both; and the provenance keys (id, store_id, created_by, requested_at, resolved_at, canceled_at, created_at, updated_at).

order_id
string
required

Required. The placed order this claim is raised against, and immutable: nothing in this family moves a claim to another order, because the claimed lines are that order's lines. It sits in the body rather than the path because the resource and its four transitions live under /order-claims, and a create one segment away under a different prefix would split one resource across two.

type
enum<string>
required

Required, with NO default, because a claim settled in money and one settled by shipping a replacement are different promises to the shopper. It is fixed at creation and no transition changes it, and it is what decides whether POST /api/v1/order-claims/{claimId}/resolve moves money or triggers a replacement. A value outside the two answers 400.

Available options:
refund,
replace
items
object[]
required

The claimed lines, in the order they are stored and served in, so a client that reorders its request reorders the resource. More than 200 answers 400 invalid_quantity rather than a code of its own.

Required array length: 1 - 200 elements
images
string[]

Optional evidence photos, in the order they are stored and served in. An empty or omitted list is the ordinary case, since an integration opening a claim from a support ticket usually has no photo. More than 20 answers 400.

Maximum array length: 20

An https url to a public host, validated when it is written: an ip literal that is loopback, private, link-local, carrier-NAT or unspecified answers 400, so a claim cannot be used to point staff screens at internal infrastructure.

Response

Created

data
object