Files
pokemon-inventory/docs/API.md
T
2026-09-10 00:51:05 -04:00

6.4 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/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

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/jobs/:id
GET    /api/v1/admin/products/:id/provider-mappings
POST   /api/v1/admin/products/:id/provider-mappings
POST   /api/v1/admin/provider-mappings/:id/disable

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/inventory/:id/pricing/refresh
POST   /api/v1/admin/bulk

`POST /api/v1/admin/bulk` supports `ARCHIVE`, `PRICING_REFRESH`, and `TAGS` actions. `TAGS` accepts `add` and/or `remove` arrays and applies labels to the selected items' Products.

GET    /api/v1/admin/dashboard
GET    /api/v1/admin/exports/inventory.json
GET    /api/v1/admin/exports/inventory.csv

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.

Pricing refresh returns 202 Accepted with a durable job identifier and PENDING status. Poll the job endpoint for PROCESSING, COMPLETED, or FAILED; job status reads are seller-scoped and expose only safe status/error metadata. Refresh enqueue resolves the provider from an active Product-level mapping and returns 409 when no mapping exists.

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.