# Auction HTTP + Socket contract

The Auction API uses one authenticated, role-aware resource. Client and Provider
bearer tokens reach the same list/details endpoints; the backend derives visibility,
tabs, DTO fields, and allowed actions from the authenticated profile.

Socket.IO is the only application bidding surface. HTTP remains responsible for
Auction lifecycle, participation, settlement, and privacy-safe bid history.

## Canonical OpenAPI surface

| Method | Path | Actor | Purpose |
|---|---|---|---|
| GET | `/auctions` | Client / Provider | Role-aware paginated list and status tabs |
| GET | `/auctions/details?id={id}` | Client / Provider | Role-aware operational details |
| POST | `/auction` | Provider | Create a productless Auction in `Pending` |
| PUT | `/auctions/update` | Provider owner | Set `openingPrice` on an `Accepted` Auction, then publish it as `Upcoming` |
| POST | `/auctions/join` | Client | Pay deposit using `wallet` or start `online` payment |
| POST | `/auctions/cancel` | Provider owner | Cancel before start and process due refunds |
| POST | `/auctions/end` | Provider owner | Safe finalizer fallback after the end time |
| POST | `/auctions/accept-winner` | Provider owner | Accept the frozen highest bid |
| POST | `/auctions/reject-winner` | Provider owner | Reject it once; no automatic second winner |
| POST | `/auctions/winner-payment` | Winning Client | Pay the server-calculated remaining amount |
| GET | `/auctions/bids?id={id}` | Client / Provider | Privacy-safe bid history |

Command resource identifiers live in the multipart body whenever another value is
submitted. Shared Auction reads use an explicit `id` query value; mutation ids stay in
the request body whenever the operation accepts other values.

`PUT /auctions/update` accepts exactly `id` and `openingPrice` in the body. Both are
required; the Auction must be owned by the authenticated Provider and still be in the
`Accepted` tab. Success publishes it immediately into `Upcoming`.

## Creation contract

Auction creation is not tied to a Product. Required inputs are `name`, `description`,
`images`, `depositAmount`, `startDate`, and `durationHours` (5–24).
The server calculates `endDate`; clients cannot submit lifecycle, winner, financial,
or moderation fields. At creation it freezes `vatTax`, `auctionAppPercentage`, and
`auctionTypeAppPercentage` from the dashboard settings into the Auction. The Provider
cannot submit or override them. The monetary `vatPrice` and `appCommission` remain
unset until the winner pays, when they are calculated from the frozen rules and final
price and stored on the Auction for dashboard reporting only.

## Role tabs

`GET /auctions` requires the query parameter `type` on every request.

- Client: `upcoming`, `current`, `finished`.
- Provider: `pending`, `accepted`, `rejected`, `upcoming`, `current`, `finished`.

`current` is the public request value for the internally live Auction state. Values
outside the authenticated role's list return a validation error.

## Admin approval schedule

Approving an Auction in the dashboard creates two persistent jobs initially:

1. `<auctionId>-publish-auction` makes the approved Auction visible to Clients in
   `upcoming` at `max(approvedAt, startAt - auctionPublishBeforeStartHours)`.
2. `<auctionId>-start-auction` changes its status to `current` at `startAt`.
   After this transition succeeds, the start handler creates and activates
   `<auctionId>-end-auction`, which finalizes the Auction at `endAt`.

`auctionPublishBeforeStartHours` is managed from the dashboard Auction settings. For
example, a 10-hour lead publishes an Auction starting in 12 hours after 2 hours; an
Auction starting in 1 hour is published immediately when approved. Publication is
tracked by the persistent CronJob record, so it does not add a publication field to
the Auction model. Changing the dates of an approved Auction before it starts
reschedules the publication and start jobs; the end job is created when the Auction
actually starts.

## Payments and idempotency

- Join and winner settlement require `paymentMethod=wallet|online`.
- Wallet mutations use transactions and replay-safe financial references.
- Online requests create a pending `AuctionPayment` and return HTTP `202`; an Auction
  is never marked paid or joined without verified gateway confirmation.
- Socket bid retries require `idempotencyKey` and use the atomic compare-and-set path.
- Refund records are idempotent, so cancellation/finalization retries cannot credit
  the same deposit twice.

## Statuses

`Pending`, `Rejected`, `Accepted`, `Upcoming`, `Live`, `Finished`, `Cancelled`,
`WinnerAccepted`, `WinnerRejected`, `AwaitingPayment`, `Paid`, `Completed`.

Every state transition writes `AuctionStatusHistory`. Client-facing DTOs do not expose
the admin minimum price, other participants' payment data, raw wallet records, or
idempotency keys.

Successful Wallet winner settlement creates one Order linked by `auction`. Auction
Orders are productless: their display data comes from the immutable Auction name/image
snapshot stored in `Order.productDetails`; normal store Orders still require `product`.

## Runtime surface

`AuctionRoute` registers only the 11 operations in the canonical OpenAPI table above.
The independent `/my-bids` utility remains owned by `BidRoute`; it is not part of the
Auction Swagger group.

## Removed duplicate surfaces

`/provider/auctions` and its command children, `/auctions/deposit`,
`/auctions/deposit-status`, `/auctions/my-result`, `/place-bid`, `/list-auctions`,
`/auction-details`, `/auction-bids`, `/bids-list`, `/create-product-auction`,
`/pay-auction-deposit`, `/pay-auction`, `/update-auction`, `/cancel-auction`, and
`/auctions/bid`. The old AuctionRoute utilities `/auction-subscriptions`,
`/auctions/similar`, `/auctions/favourite`, `/auctions/report`,
`/conversations/auction`, and the Haraj-style Auction routes are also no longer
registered by `AuctionRoute`.

Push deep-links use `service: /auctions` plus `auctionId`.

Socket details: [`AUCTION_SOCKET_EVENTS.md`](./AUCTION_SOCKET_EVENTS.md).
