API documentation
The read API is public, returns JSON, and allows cross-origin GET requests. Prices are decimal amounts in the product's currency.
List products
GET /api/v1/products
| Query | Default | Description |
|---|---|---|
category | — | Only products in this category (lowercase). |
page | 1 | Page number, starting at 1. |
per_page | 20 | Items per page, 1–100. |
{
"data": [
{
"id": "6f1c0d52-1c1e-4d57-9d0e-3f2f4b7e2a10",
"name": "Arc Floor Lamp",
"description": "Sample product: brushed-steel floor lamp.",
"price": 189,
"currency": "USD",
"image_url": null,
"category": "lighting",
"is_sample": true,
"created_at": "2026-10-29T12:00:00.000Z",
"updated_at": "2026-10-29T12:00:00.000Z"
}
],
"meta": { "page": 1, "per_page": 20, "total": 1, "total_pages": 1 }
}Get one product
GET /api/v1/products/:id
Returns { "data": { … } }, or 404 with { "error": { "code": "not_found" } }.
Errors
Invalid query parameters return 400 with { "error": { "code": "invalid_query", "issues": { … } } }.
Fetch example
const res = await fetch("https://YOUR-HOST/api/v1/products?category=lighting&page=1");
const { data, meta } = await res.json();
data.forEach((p) => console.log(p.name, p.price));Writing products
Products are created, edited and deleted in the password-protected admin. The public API is read-only.