Quality / test (push) Canceled after 0s
Document the shipped acquisition, sales, pricing, dashboard, search, public detail, and image workflows, and update the next hardening milestone.
166 lines
5.6 KiB
Markdown
166 lines
5.6 KiB
Markdown
# API
|
|
|
|
## Base
|
|
|
|
REST API under `/api/v1`.
|
|
|
|
Responses use:
|
|
|
|
```json
|
|
{ "data": {} }
|
|
```
|
|
|
|
Collections include pagination metadata.
|
|
|
|
## Public endpoints
|
|
|
|
```text
|
|
GET /api/v1/public/search
|
|
GET /api/v1/public/products/:slug
|
|
GET /api/v1/public/inventory
|
|
GET /api/v1/public/inventory/:id
|
|
GET /api/v1/public/listings
|
|
GET /api/v1/public/listings/:id
|
|
GET /api/v1/public/sellers
|
|
GET /api/v1/public/lookups/categories
|
|
GET /api/v1/public/lookups/conditions
|
|
GET /api/v1/public/currencies
|
|
GET /api/v1/public/exchange-rates
|
|
```
|
|
|
|
## Authentication
|
|
|
|
```text
|
|
POST /api/v1/auth/login
|
|
POST /api/v1/auth/logout
|
|
POST /api/v1/auth/forgot-password
|
|
POST /api/v1/auth/reset-password
|
|
GET /api/v1/auth/me
|
|
POST /api/v1/auth/mfa/enroll
|
|
POST /api/v1/auth/mfa/verify
|
|
POST /api/v1/auth/mfa/disable
|
|
GET /api/v1/auth/sessions
|
|
DELETE /api/v1/auth/sessions/:id
|
|
DELETE /api/v1/auth/sessions
|
|
```
|
|
|
|
`POST /api/v1/auth/forgot-password` always returns the same accepted response after validating an email-shaped request, whether or not an account exists. It sends an opaque, one-time reset token only through the configured mail adapter. `POST /api/v1/auth/reset-password` consumes that token, updates the password, and revokes all active sessions.
|
|
|
|
`GET /api/v1/auth/sessions` returns only the authenticated user's active sessions and marks the current session. It never returns session or CSRF token material. `DELETE /api/v1/auth/sessions/:id` revokes one session owned by the authenticated user. `DELETE /api/v1/auth/sessions` revokes all other active sessions while retaining the current session. Session revocation endpoints require CSRF validation.
|
|
|
|
## Admin endpoints
|
|
|
|
```text
|
|
GET /api/v1/admin/products
|
|
POST /api/v1/admin/products
|
|
GET /api/v1/admin/products/:id
|
|
PATCH /api/v1/admin/products/:id
|
|
|
|
GET /api/v1/admin/inventory
|
|
POST /api/v1/admin/inventory
|
|
GET /api/v1/admin/inventory/:id
|
|
PATCH /api/v1/admin/inventory/:id
|
|
POST /api/v1/admin/inventory/:id/list
|
|
POST /api/v1/admin/inventory/:id/archive
|
|
POST /api/v1/admin/inventory/:id/relist
|
|
POST /api/v1/admin/inventory/:id/pricing/refresh
|
|
|
|
GET /api/v1/admin/listings
|
|
GET /api/v1/admin/listings/:id
|
|
PATCH /api/v1/admin/listings/:id
|
|
POST /api/v1/admin/listings/:id/publish
|
|
POST /api/v1/admin/listings/:id/unpublish
|
|
POST /api/v1/admin/listings/:id/pending
|
|
POST /api/v1/admin/listings/:id/archive
|
|
|
|
POST /api/v1/admin/pricing/refresh
|
|
GET /api/v1/admin/jobs/:id
|
|
|
|
POST /api/v1/admin/inventory/:id/images
|
|
PATCH /api/v1/admin/inventory/:id/images/order
|
|
POST /api/v1/admin/images/:id/primary
|
|
DELETE /api/v1/admin/images/:id
|
|
|
|
GET /api/v1/admin/acquisitions
|
|
POST /api/v1/admin/acquisitions
|
|
GET /api/v1/admin/sales
|
|
POST /api/v1/admin/sales
|
|
POST /api/v1/admin/sales/:id/void
|
|
POST /api/v1/admin/pricing/observations
|
|
POST /api/v1/admin/inventory/:id/valuation
|
|
POST /api/v1/admin/inventory/:id/valuation/override
|
|
POST /api/v1/admin/bulk
|
|
|
|
GET /api/v1/admin/dashboard
|
|
|
|
GET /api/v1/admin/saved-views
|
|
POST /api/v1/admin/saved-views
|
|
PATCH /api/v1/admin/saved-views/:id
|
|
DELETE /api/v1/admin/saved-views/:id
|
|
```
|
|
|
|
Listing creation and lifecycle writes require an authenticated admin session and
|
|
the session-bound CSRF header. Publishing is seller-scoped and checks the
|
|
persisted product, category, condition, asking price, physical inventory, and
|
|
image prerequisites before changing a draft to `AVAILABLE`; sold and archived
|
|
physical inventory cannot be published. Unpublish changes
|
|
an available listing to `CLOSED`; pending changes are available from draft or
|
|
available listings.
|
|
|
|
`POST /api/v1/admin/inventory/:id/images` stores validated image metadata for an
|
|
owned physical inventory item. File bytes are handled by the future
|
|
`ImageStorage` adapter; JSON metadata and multipart image uploads are accepted.
|
|
Multipart uploads require `width` and `height` fields and validate the binary
|
|
signature before storage. Publication counts persisted inventory images rather
|
|
than trusting a listing request field.
|
|
|
|
Acquisition, sale, pricing, and dashboard routes are seller-scoped through the
|
|
authenticated admin session. All state-changing routes require the
|
|
session-bound CSRF header. Sale creation marks owned active inventory items as
|
|
`SOLD`; voiding retains the sale record, restores the items to `ACTIVE`, and
|
|
records an audit event. Pricing observations remain private; public listing
|
|
detail exposes only the latest calculated or manually overridden market value,
|
|
condition label, and public image URLs.
|
|
|
|
## Provider matching
|
|
|
|
The API must expose Product-level operations for:
|
|
- searching configured providers for candidate matches
|
|
- confirming a provider mapping
|
|
- manually searching/refining a provider query
|
|
- marking a provider not applicable
|
|
- disabling/replacing a mapping
|
|
|
|
Exact route naming may be finalized during API implementation, but these operations must remain Product-scoped.
|
|
|
|
## Validation
|
|
|
|
Validate body, query, path, and response schemas.
|
|
|
|
Business validation occurs after request-shape validation.
|
|
|
|
Allowlist sortable fields.
|
|
|
|
## Errors
|
|
|
|
Use machine-readable codes, including:
|
|
- `PRODUCT_NOT_FOUND`
|
|
- `INVENTORY_NOT_FOUND`
|
|
- `INVENTORY_EDIT_LOCKED`
|
|
- `INVALID_STATUS_TRANSITION`
|
|
- `LISTING_REQUIREMENTS_NOT_MET`
|
|
- `SALE_PRICE_REQUIRED`
|
|
- `SALE_ITEM_NOT_AVAILABLE`
|
|
- `PRICING_PROVIDER_FAILED`
|
|
- `IMAGE_LIMIT_EXCEEDED`
|
|
- `UNAUTHORIZED`
|
|
- `FORBIDDEN`
|
|
|
|
## Privacy
|
|
|
|
Public DTOs must never expose private acquisition, sale, buyer, internal, provider-debugging, pricing-history, or audit information.
|
|
|
|
## Pagination and query state
|
|
|
|
Large collections use pagination. Public/admin filters and searches should be represented in URL query state where useful for shareability, refresh, and back/forward navigation.
|