Files
pokemon-inventory/docs/API.md
T
fragginwagon f7152bcff3 feat: add multipart image uploads
Register Fastify multipart support, validate JPEG/PNG/WebP binary signatures, store upload bytes through ImageStorage, persist metadata after storage succeeds, clean up bytes on metadata failure, and document the upload boundary. Verification: npm test passed 68 tests and integration passed 14 tests. No build script is configured.
2026-09-08 17:38:27 -04:00

4.7 KiB

API

Base

REST API under /api/v1.

Responses use:

{ "data": {} }

Collections include pagination metadata.

Public endpoints

GET /api/v1/public/search
GET /api/v1/public/products/:slug
GET /api/v1/public/inventory
GET /api/v1/public/listings
GET /api/v1/public/sellers
GET /api/v1/public/currencies
GET /api/v1/public/exchange-rates

Authentication

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

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

POST   /api/v1/admin/sales
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.

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.