Public API · Competitors

Competitors API — retailers + listings, one model.

Add retailers, match their URLs to your SKUs, pull observations. Same primitives the dashboard uses; surfaced for your stack.

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

Competitor entities

A Competitor is a retailer you monitor (e.g. amazon.de, mediamarkt.de). Each is enabled per tenant and carries country + category metadata used by the scraper to pick the right extraction strategy.

GET/api/public/v1/competitorsBearer pk_live_…

List competitors with optional country filter. Includes the count of products tracked against each.

Body
Query: country?, limit? (1–200, default 50)
Returns
{ data: Competitor[], count: number } — Competitor = { id, domain, displayName, country, category, enabled, trackedProducts, createdAt }
curl "https://api.priceroom.com/api/public/v1/competitors?country=de" \
  -H "Authorization: Bearer pk_live_XXX"
POST/api/competitorsCookie session

Add a competitor to the tenant.

Body
domain* (3–120, lowercase), displayName* (1–120), country? (default 'de'), category? (electronics | fashion | grocery | home | sports | …)
Returns
Created Competitor document
curl -X POST https://app.priceroom.com/api/competitors \
  -H "Content-Type: application/json" \
  -H "Cookie: pr_session=..." \
  -d '{
    "domain": "mediamarkt.de",
    "displayName": "MediaMarkt",
    "country": "de"
  }'
GET/api/competitorsCookie session

List all competitors for the tenant.

Body
Returns
Array of { _id, displayName, domain }
PATCH/api/competitors/[id]Cookie session

Partial update of competitor fields.

Body
displayName?, domain?, country?, category?, enabled?, priority? (0–10 | null)
Returns
Updated Competitor document
DELETE/api/competitors/[id]Cookie session

Soft-delete the competitor (and its matched listings).

Body
Returns
{ ok: true }

Competitor products (matches)

The bridge entity between your Product and a Competitor URL. A CompetitorProduct is the actual scraped listing — its `currentPrice`, `currentStock`, and `priceHistory` are populated by the scraper or by direct PATCHes.

POST/api/competitor-productsCookie session

Match a product to a competitor URL.

Body
productId*, competitorId*, url* (≤ 2048 chars), matchMethod? (manual | ai | gtin | image | title-fuzzy), matchScore? (0–1)
Returns
Created CompetitorProduct document
GET/api/competitor-productsCookie session

List matches, optionally filtered by productId and / or competitorId.

Body
Query: productId?, competitorId? (limit 500)
Returns
CompetitorProduct[] (productId + competitorId populated with displayName)
PATCH/api/competitor-products/[id]Cookie session

Update a match. Supplying `currentPrice` (integer cents) auto-appends to priceHistory (kept at the last 200 entries).

Body
url?, currentPrice? (cents), currentStock? (bool), lastCheckedAt? (ISO), enabled?, matchMethod?, matchScore?
Returns
Updated CompetitorProduct document
DELETE/api/competitor-products/[id]Cookie session

Soft-delete the match.

Body
Returns
{ ok: true }

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..."
  }
}