# Product API Alongside the server-rendered store, the platform exposes a **versioned JSON API** for products — for mobile clients, integrations, and headless use. ## Design - **REST + JSON** under a versioned namespace, so the contract can evolve without breaking existing clients. - **Cursor-paginated** list endpoints (see [Scaling](/architecture/scaling/)) — stable, fast pagination that does not drift when the catalog changes mid-scroll. - **Filtering and search** that reuse the same query objects as the web store, so API and web results stay consistent. - **Authorization** through the same Pundit policies as the rest of the app — the API is not a side door around the permission model. ## Documented with OpenAPI The API is specified with **rswag**, which generates an OpenAPI (Swagger) document straight from the request specs. That means: - The docs are **generated from tests** — if the spec passes, the documentation is accurate by construction. - A browsable **Swagger UI** is served at `/api-docs` for trying endpoints interactively. ``` bundle exec rspec spec/requests/api # tests + regenerates the OpenAPI spec ``` This closes the usual gap where hand-written API docs rot out of sync with the implementation. ## Why it ships with the monolith The API is a thin presentation layer over the same models, query objects, and policies the web store uses. Splitting it into its own service would have meant duplicating that logic or adding a network hop to reach it. Keeping it in the monolith means one source of truth for product data and one place to change it. ## Key files | Concern | Files | |---------|-------| | Controllers | `app/controllers/api/`, `app/services/api/` | | Pagination | `CursorPaginator` | | Docs | `rswag`, request specs under `spec/requests/`, Swagger UI at `/api-docs` |