Public API · Products

Products API — every SKU, programmable.

CRUD over your catalogue, plus on-demand observation kicks. The same shapes the dashboard renders, behind a stable URL.

Base URL
api.priceroom.com/api/public/v1
Format
application/json
Auth
Bearer token
Rate limit
600 req/min/key

Catalogue CRUD

Cookie-session endpoints used by the in-app product workflows. The same shapes are exposed under /api/public/v1/products for external integrations.

GET/api/public/v1/productsBearer pk_live_…

List products with cursor pagination. Filter by brand, category, or tier.

Body
Returns
{ data: Product[], nextCursor: string | null, count: number }
curl "https://api.priceroom.com/api/public/v1/products?limit=50&brand=Sony" \
  -H "Authorization: Bearer pk_live_XXX"
{
  "data": [
    {
      "id": "6630e1...",
      "sku": "WH-1000XM5",
      "title": "Sony WH-1000XM5 Wireless Headphones",
      "brand": "Sony",
      "category": "Audio",
      "tier": "premium",
      "ourPrice": 29900,
      "costPrice": 18000,
      "targetPrice": 30900,
      "currency": "EUR",
      "createdAt": "2026-04-13T16:05:12Z",
      "updatedAt": "2026-05-02T09:11:48Z"
    }
  ],
  "nextCursor": "eyJ0IjoxNzE5NjIzMjAwfQ==",
  "count": 1
}
POST/api/productsCookie session

Create a product in the tenant catalogue.

Body
sku*, title*, brand?, category?, ourPrice? (cents), costPrice? (cents), targetPrice? (cents), currency? (default EUR), vintage? (1900–2100), bottleSizeMl?, packagingSize?, region?, appellation?, b2bMinPrice?, attributes? (record, ≤ 50 keys)
Returns
Created Product document
curl -X POST https://app.priceroom.com/api/products \
  -H "Content-Type: application/json" \
  -H "Cookie: pr_session=..." \
  -d '{
    "sku": "WH-1000XM5",
    "title": "Sony WH-1000XM5",
    "brand": "Sony",
    "ourPrice": 29900,
    "currency": "EUR"
  }'
GET/api/products/[id]Cookie session

Fetch a single product by Mongo ObjectId.

Body
Returns
Full Product document
PATCH/api/products/[id]Cookie session

Partial update. Same fields as POST, all optional.

Body
sku?, title?, brand?, category?, gtin?, ourPrice?, costPrice?, targetPrice?, tier?, currency?, vintage?, attributes? …
Returns
Updated Product document
DELETE/api/products/[id]Cookie session

Soft-delete (sets deletedAt). The doc is not removed.

Body
Returns
{ ok: true }

Live observations

Trigger or query competitor-price observations attached to a product.

POST/api/products/[id]/scrape-nowCookie session

Kick off an ad-hoc scrape across every enabled CompetitorProduct matched to this product. Returns the new run id; poll /api/scrape-runs/[runId] for status.

Body
Returns
{ ok: true, runId: string, status: 'queued' | 'running', targetsCount: number, successCount: number, failCount: number }
curl -X POST https://app.priceroom.com/api/products/6630e1.../scrape-now \
  -H "Cookie: pr_session=..."
GET/api/public/v1/observationsBearer pk_live_…

Flatten observation history across competitor matches. Filter by productId, competitorId, or ISO date range.

Body
Query: productId?, competitorId?, from? (ISO), to? (ISO), limit? (1–500, default 100)
Returns
{ data: Observation[], count: number, total: number }

Errors

Every 4xx/5xx returns a stable JSON error. Use code for programmatic branching.

{
  "error": {
    "code": "invalid_api_key",
    "message": "The provided API key is invalid or revoked.",
    "requestId": "req_01HTX9..."
  }
}