Skip to content

GET /v3/item/:id — item detail

GET
/v3/item/{itemId}
curl --request GET \
--url https://api-ha-prod-p8.handbid.dev/v3/item/example \
--header 'Authorization: Bearer <token>'

NEW (HAN-1686, 2026-05-07; expanded by HAN-1907 2026-05-27). Item-detail screen payload — full content for the card-tap → detail flow on iOS. Strict superset of the items-list card shape plus full description / image carousel / per-caller bidding state.

Auth: OPTIONAL. Bearer token flips the per-user fields isCurrentUserWinning, userAutoBidMax, isFavorite, and hasCurrentUserBid. Missing/invalid token degrades silently to anonymous (same opportunistic pattern as /v3/auction/:id/items).

Wire shape — identity + core:

  • id, auctionId, auctionGuid, name, itemType
  • statusId + status (string label)
  • itemCode, categoryId, categoryName
  • currency (3-letter ISO code; defaults to USD when the auction has no configured currency)

Money + bid state:

  • currentPrice, startingPrice, bidIncrement, minimumBidAmount, buyNowPrice (nullable), marketValue, reservePrice (nullable), showValue (bool — whether the auction is configured to expose marketValue on the card)
  • bidCount, bidderCount — both hook-maintained from item_stats (validBidQuantity + validBidderCount); zero allocations during the read.
  • closingTime (epoch, nullable — cascades item → category → auction timer)

Inventory + tickets:

  • hasInventory (bool), inventoryTotal, quantitySold — all from item_stats.quantitySold. inventoryRemaining is null when hasInventory=0.
  • admits (ticket items only — admission count), ticketInstructions (string; null for non-ticket items)

Long-form content (the reason this endpoint exists vs the list shape):

  • description — full text (legacy WYSIWYG may emit HTML).
  • finePrint — sourced from items.notables (legacy column name).
  • videoEmbedCode, redemptionInstructions, donor — all nullable.
  • images[] — full carousel as [{ url, isPrimary }]. Sorted: primary first, then by ord, then by itemImageId.

Auction context (so the client can detect staleness without a separate auction-state poll):

  • auctionStatusId, auctionEndTime, auctionTimerStartTime, auctionTimerEndTime, auctionShowName (whether to display real bidder names vs paddle numbers).

Winner + per-caller state:

  • winnerId (nullable; from item_stats.highestBidIdbids.userId).
  • winningBidderLabel (nullable) — composed per auctionShowName rules: "Full Name (#paddleId)" when showName=true and a name is available, else alias, else "Paddle#paddleId".
  • isCurrentUserWinning (bool) — true iff winnerId == currentUserId (always false on anonymous reads).
  • userAutoBidMax (decimal, nullable) — caller’s active max_bids.amount for this item if any.
  • isFavorite (bool, always present) — user_favorite_item_relation EXISTS for caller (always false on anonymous).
  • isFeatured (bool) — auction-scoped featured flag.
  • controlMode — string enum; same derivation + 9-value range as the items-list endpoint (purchase / donate / bid-with-buy-now / bid / sealed-bid / competitive-bid / bidbox / puzzle / view-only).
  • hasCurrentUserBid (bool, always present) — NEW (HAN-1907) — true iff the caller has at least one bid row on this item with status IN ('winning', 'losing', 'purchase') (the V3 active-bid allowlist — MY_ACTIVITY_BID_STATUSES). Excludes lifecycle/terminal states (failed, removed, replaced, incomplete, sold_out, winning_changed, transferred) because those bids no longer “matter now” for the outbid-banner state. Drives the iOS “you’ve been outbid” banner — distinguishes “you bid and got outbid” from “you never bid.” Always false on anonymous reads.

Errors:

  • 400 when :id is non-positive.
  • 404 not_found for missing, soft-deleted, deleted-events-org, test-auction, item-status-outside-visible-set, or privacy-blocked items. Privacy gate is identical to /v3/auction/:id/items so an item visible in the list is always reachable via the detail endpoint.

Cache: per-user key v3:item:{id}:detail:{userId|anon}, 30s TTL, tagged on V3CacheTags::auction($auctionId) + V3CacheTags::userFavorites($userId) when authed. Bid placement/removal/replacement from any origin (V3 POST, manager, V1, purchase) invalidates the auction tag via HbBid::afterSave() / afterDelete(), so hasCurrentUserBid and isCurrentUserWinning flip on the next read without a TTL wait.

itemId
required
string

Successful response

Media type application/json