# Orders and Payments API All `/api/v1` customer endpoints derive ownership from authentication. ## Orders - `POST /orders/from-checkout` converts an owned READY checkout. Conversion locks the checkout, verifies ACTIVE reservations, copies immutable snapshots, converts the cart, and is idempotent by unique checkout ID. - `GET /orders` and `GET /orders/:id` provide owner-scoped history/detail. - `POST /orders/:id/cancel` releases unpaid reservations. Paid orders require an explicit refund. - Admin: `GET /admin/orders`, `GET /admin/orders/:id`, cancel, and mark-processing action endpoints. Legal transitions are centralized. Payment, order, and fulfillment status are separate. ## Payments and webhooks - `POST /orders/:id/payment`, `GET /orders/:id/payment` - `POST /payments/webhooks/payhere` is unauthenticated at the session layer but requires the PayHere merchant hash. Online browser redirects are never authoritative. A verified webhook must match local payment reference, currency, and DECIMAL amount. Unique provider event IDs make retries idempotent. A first successful event consumes each reservation once, records coupon redemption, marks payment/order paid, and issues invoice metadata. Failure does not consume inventory. PayHere configuration uses `PAYHERE_MERCHANT_ID`, `PAYHERE_MERCHANT_SECRET`, and notify/return/cancel URLs. Stripe has an explicit disabled adapter until its official SDK and webhook secret are configured. No raw card or provider secret is accepted or returned. ## Invoices - `GET /orders/:id/invoice` is owner-scoped. Invoice numbers use the locked ReferenceNumber sequence. Invoice metadata is created once per paid order. PDF generation is reserved for the existing document worker integration; no second PDF/storage subsystem was introduced. ## Refunds - `POST /admin/orders/:id/refunds` requires `payments.refund` and `Idempotency-Key`. Requested item quantities and captured totals are locked and validated. A refund never restocks inventory automatically. Provider refund execution remains disabled until provider API credentials/workflows are validated. ## Returns - Customer: `POST /orders/:orderId/returns`, `GET /returns`, `GET /returns/:id`. - Admin: list, approve, reject, mark-received, and complete actions. The return window uses `RETURN_WINDOW_DAYS` (default 30). Quantity cannot exceed the remaining purchased quantity. Only accepted RESTOCKABLE items are added through the inventory service; damaged/non-restockable items are not. EXCHANGE records intent only. Business credit purchasing is intentionally disabled: no locked credit ledger was added without an approved accounting policy. Delivery, loyalty, support AI, and analytics are outside Phase 7.