# Pricefy API
> Welcome developers, partners, and innovators! We are thrilled to introduce you to the Pricefy API — the backbone of our industry-leading Software as a Service (SaaS) solution. Whether you're looking to integrate Pricefy with your existing platforms, extract insightful data, or simply customize Pricefy to better fit your organization's needs, this documentation is your comprehensive guide.
Base URL: `https://api.pricefy.io`.
Authentication:
- REST endpoints: send the `X-Api-Key` header on every request.
- MCP endpoint (`POST /mcp`): accepts either `X-Api-Key` (Claude Desktop, Cursor, Codex, …) or OAuth Bearer (ChatGPT custom connectors). See `/docs` for the connection guide.
## OpenAPI
- [OpenAPI specification (YAML)](https://api.pricefy.io/openapi.yaml)
- [Interactive API reference](https://api.pricefy.io/docs)
- [Full content as plain text](https://api.pricefy.io/llms-full.txt)
## Welcome
Health check.
- [Health check](https://api.pricefy.io/docs?tag=Welcome&op=welcome): `GET /v1`
## Account
Merchant account, subscription and plan limits.
- [Get account](https://api.pricefy.io/docs?tag=Account&op=getMerchantAccount): `GET /v1/merchant/account`
## Store
Store information and last import.
- [Get store](https://api.pricefy.io/docs?tag=Store&op=getMerchantStore): `GET /v1/merchant/store`
## Products
Merchant product catalog. Cursor-based pagination.
- [List products](https://api.pricefy.io/docs?tag=Products&op=listProducts): `GET /v1/merchant/products`
- [Upsert products (bulk)](https://api.pricefy.io/docs?tag=Products&op=bulkUpsertProducts): `PUT /v1/merchant/products`
- [Get product](https://api.pricefy.io/docs?tag=Products&op=getProduct): `GET /v1/merchant/products/{sku}`
- [Upsert product](https://api.pricefy.io/docs?tag=Products&op=upsertProduct): `PUT /v1/merchant/products/{sku}`
- [Delete product](https://api.pricefy.io/docs?tag=Products&op=deleteProduct): `DELETE /v1/merchant/products/{sku}`
## Competitors
Competitor domains with price analysis.
- [List competitors](https://api.pricefy.io/docs?tag=Competitors&op=listCompetitors): `GET /v1/competitors`
- [Add competitor](https://api.pricefy.io/docs?tag=Competitors&op=addCompetitor): `POST /v1/competitors`
- [Update competitor status](https://api.pricefy.io/docs?tag=Competitors&op=updateCompetitorStatus): `PUT /v1/competitors`
- [Get competitor](https://api.pricefy.io/docs?tag=Competitors&op=getCompetitor): `GET /v1/competitors/{domain}`
## Monitored URLs
URLs being monitored on each competitor, with stock and price diff.
- [List monitored URLs](https://api.pricefy.io/docs?tag=Monitored%20URLs&op=listMonitoredUrls): `GET /v1/competitors/urls`
- [Upsert monitored URLs](https://api.pricefy.io/docs?tag=Monitored%20URLs&op=upsertMonitoredUrls): `PUT /v1/competitors/urls`
- [Delete monitored URLs](https://api.pricefy.io/docs?tag=Monitored%20URLs&op=deleteMonitoredUrls): `DELETE /v1/competitors/urls`
- [Monitored URL price-history detail](https://api.pricefy.io/docs?tag=Monitored%20URLs&op=getMonitoredUrlDetail): `GET /v1/competitors/urls/detail`
## MAP Infringements
Minimum Advertised Price rules and the resellers that breach them.
- [List MAP infringements](https://api.pricefy.io/docs?tag=MAP%20Infringements&op=listMapInfringements): `GET /v1/map-infringements`
- [List MAP infringement rules](https://api.pricefy.io/docs?tag=MAP%20Infringements&op=listMapInfringementRules): `GET /v1/map-infringement-rules`
## Repricing
Dynamic pricing rules and repricing previews.
- [List repricing rules](https://api.pricefy.io/docs?tag=Repricing&op=listRepricingRules): `GET /v1/dynamic-pricing/list`
- [Repricing preview](https://api.pricefy.io/docs?tag=Repricing&op=getRepricingPreview): `GET /v1/dynamic-pricing/preview`
- [Apply suggested prices](https://api.pricefy.io/docs?tag=Repricing&op=applyRepricing): `POST /v1/dynamic-pricing/apply/{rule_id}`
## Reports
Scheduled reports configuration.
- [List reports](https://api.pricefy.io/docs?tag=Reports&op=listReports): `GET /v1/reports`
- [Get report](https://api.pricefy.io/docs?tag=Reports&op=getReport): `GET /v1/reports/{id}`
## Alerts
Alert rules and triggered alerts (price/stock variations).
- [List alert rules](https://api.pricefy.io/docs?tag=Alerts&op=listAlertRules): `GET /v1/alert-rules`
- [Get alert rule](https://api.pricefy.io/docs?tag=Alerts&op=getAlertRule): `GET /v1/alert-rules/{id}`
- [Get alert rule alerts](https://api.pricefy.io/docs?tag=Alerts&op=getAlertRuleAlerts): `GET /v1/alert-rules/{id}/alerts`
- [List alert variations](https://api.pricefy.io/docs?tag=Alerts&op=listAlerts): `GET /v1/alerts`
## Postman
The **complete Pricefy API collection** lives in the [public Pricefy Postman workspace](https://www.postman.com/pricefy/workspace/pricefy-api) — every endpoint, request body, query parameter and response example, pre-wired and ready to send. Use it to explore the API in Postman desktop / web, fork it into your own workspace, or run it as part of an automated test suite via Newman.
[](https://www.postman.com/pricefy/workspace/pricefy-api)
Alternatives:
- [Browse the workspace](https://www.postman.com/pricefy/workspace/pricefy-api) directly on postman.com
- [Download the collection JSON](/postman/collection.json) and import manually into Postman or Newman
- [Download the Postman collection](https://api.pricefy.io/docs?tag=Postman&op=downloadPostmanCollection): `GET /postman/collection.json`
## MCP
**Model Context Protocol** — same Pricefy API, exposed as MCP tools so Claude Desktop, Cursor, ChatGPT, Codex and the Claude CLI can call it natively. Streamable HTTP transport, JSON-RPC 2.0, dual auth (`X-Api-Key` **or** OAuth 2.1 Bearer), same per-merchant permissions as REST. 25 tools (18 read-only + 5 write + 2 destructive). See `POST /mcp` for the full catalog and the landing page for connection guides.
- [MCP server (Streamable HTTP JSON-RPC)](https://api.pricefy.io/docs?tag=MCP&op=mcpServer): `POST /mcp`
## Full OpenAPI specification
The full machine-readable specification (YAML) is inlined below.
```yaml
openapi: "3.0.0"
info:
version: "3.10.4"
title: "Pricefy API"
description: |
Monitor your competitors' prices on autopilot.
## Authentication
REST endpoints require the `X-Api-Key` header. The MCP endpoint (`POST /mcp`) accepts **two** authentication modes — see the dedicated **MCP** section below.
## Rate Limiting
API requests are rate limited based on your subscription plan.
## Pagination
Paginated endpoints use `page` + `limit` (default 25, max 100). Products use cursor-based pagination.
## Error Codes
| Code | Description |
|------|-------------|
| 109 | Monitored URLs limit exceeded |
## Postman collection
The full API is also available in the [public Pricefy Postman workspace](https://www.postman.com/pricefy/workspace/pricefy-api). Open it online, fork it into your own workspace and start sending requests in seconds.
[](https://www.postman.com/pricefy/workspace/pricefy-api)
## MCP support (Model Context Protocol)
The Pricefy API is also exposed as an **MCP server** at `POST /mcp` (Streamable HTTP transport), so AI clients like Claude Desktop, Cursor, ChatGPT, Codex, and the Claude CLI can call it as native tools.
**25 tools** are exposed (18 read-only + 5 write + 2 destructive). Write and destructive tools are annotated so MCP clients can show a confirmation dialog before invoking them; only the two destructive tools (`delete_product`, `batch_delete_monitored_urls`) permanently remove data. Read-only ones include `list_products`, `list_competitors`, `list_monitored_urls`, `get_monitored_url_detail`, `list_alerts`, `get_account`, `get_report`, etc. Write ones include `upsert_product`, `bulk_upsert_products`, `add_competitor`.
You can connect Pricefy to your AI client in two ways — pick whichever your client supports:
| Method | When to use it |
|---|---|
| **API key** | Claude Desktop, Cursor, Codex, `claude mcp add` — any client where you can paste your Pricefy API key into a custom header. |
| **OAuth** | ChatGPT custom connectors and any other client that doesn't let you set a custom header. You sign in with your Pricefy account and choose what the AI can do on a permission screen. |
Either way, permissions are honored at every tool call: a read-only authorization can never trigger a write or destructive tool.
### Connect Claude Desktop or Cursor (API key)
```json
{
"mcpServers": {
"pricefy": {
"type": "http",
"url": "https://api.pricefy.io/mcp",
"headers": { "X-Api-Key": "YOUR_PRICEFY_API_KEY" }
}
}
}
```
### Connect via the `claude` CLI (API key)
```bash
claude mcp add pricefy https://api.pricefy.io/mcp \
--transport http \
--header "X-Api-Key: YOUR_PRICEFY_API_KEY"
```
### Connect ChatGPT custom connector (OAuth)
Available on ChatGPT plans that include custom connectors (Plus / Pro / Business / Enterprise / Edu). In ChatGPT:
1. Settings → **Connectors** → **Advanced** → enable **Developer Mode**
2. Click **New App** and fill in:
- **Name**: `Pricefy`
- **MCP Server URL**: `https://api.pricefy.io/mcp`
- **Authentication**: `OAuth`
3. Click **Create**.
4. ChatGPT opens a Pricefy sign-in page in your browser. Sign in with your usual Pricefy credentials, choose what ChatGPT can do for each permission group on the consent screen, then click **Allow**.
5. You're back in ChatGPT — the 25 Pricefy tools are now available.
Each OAuth connection appears in **[dashboard.pricefy.io → Settings → API Keys](https://dashboard.pricefy.io/settings/api-key)** with an "OAuth" badge and a timestamped label such as `MCP Integration ChatGPT 2026-05-22-14-32-07`. To revoke a connection, just toggle it off (or delete it) from that page — the AI immediately loses access on its next call.
> Companion files for AI/LLM consumers: [`/llms.txt`](/llms.txt) (lightweight index) and [`/llms-full.txt`](/llms-full.txt) (full spec inlined), generated server-side from this OpenAPI document.
servers:
- url: "https://api.pricefy.io"
description: Production
tags:
- name: Welcome
description: Health check.
- name: Account
description: Merchant account, subscription and plan limits.
- name: Store
description: Store information and last import.
- name: Products
description: Merchant product catalog. Cursor-based pagination.
- name: Competitors
description: Competitor domains with price analysis.
- name: Monitored URLs
description: URLs being monitored on each competitor, with stock and price diff.
- name: MAP Infringements
description: Minimum Advertised Price rules and the resellers that breach them.
- name: Repricing
description: Dynamic pricing rules and repricing previews.
- name: Reports
description: Scheduled reports configuration.
- name: Alerts
description: Alert rules and triggered alerts (price/stock variations).
- name: MCP
description: |
**Model Context Protocol** — same Pricefy API, exposed as MCP tools so Claude Desktop, Cursor, ChatGPT, Codex and the Claude CLI can call it natively. Streamable HTTP transport, JSON-RPC 2.0, dual auth (`X-Api-Key` **or** OAuth 2.1 Bearer), same per-merchant permissions as REST. 25 tools (18 read-only + 5 write + 2 destructive). See `POST /mcp` for the full catalog and the landing page for connection guides.
- name: Postman
description: |
The **complete Pricefy API collection** lives in the [public Pricefy Postman workspace](https://www.postman.com/pricefy/workspace/pricefy-api) — every endpoint, request body, query parameter and response example, pre-wired and ready to send. Use it to explore the API in Postman desktop / web, fork it into your own workspace, or run it as part of an automated test suite via Newman.
[](https://www.postman.com/pricefy/workspace/pricefy-api)
Alternatives:
- [Browse the workspace](https://www.postman.com/pricefy/workspace/pricefy-api) directly on postman.com
- [Download the collection JSON](/postman/collection.json) and import manually into Postman or Newman
paths:
/v1:
get:
summary: Health check
operationId: welcome
tags: [Welcome]
responses:
200:
description: A message greeting the merchant
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessfulOperation"
401:
$ref: "#/components/responses/Unauthorized"
/v1/merchant/account:
get:
summary: Get account
operationId: getMerchantAccount
tags: [Account]
responses:
200:
description: Account information for the merchant
content:
application/json:
schema:
$ref: "#/components/schemas/Account"
401:
$ref: "#/components/responses/Unauthorized"
/v1/merchant/store:
get:
summary: Get store
operationId: getMerchantStore
tags: [Store]
responses:
200:
description: Store information for the merchant
content:
application/json:
schema:
$ref: "#/components/schemas/Store"
401:
$ref: "#/components/responses/Unauthorized"
/v1/merchant/products:
get:
summary: List products
operationId: listProducts
tags: [Products]
description: |
Returns the merchant's product catalog with cursor-based pagination.
Supports filtering by search (name/sku/gtin), brand, category, status, and price range (min_price/max_price columns).
All price fields are returned as numbers (not strings).
parameters:
- in: query
name: limit
schema:
type: integer
default: 25
description: Number of results to return (max 100)
- in: query
name: cursor
schema:
type: string
description: Cursor for pagination (from `next_page`)
# v2.1.0 filters
- in: query
name: search
schema:
type: string
minLength: 3
description: Search by name (LIKE), sku, or gtin (exact match)
- in: query
name: brand
schema:
type: string
description: Filter by brand (exact match)
- in: query
name: category
schema:
type: string
description: Filter by category (exact match)
- in: query
name: status
schema:
type: string
enum: [active, inactive]
description: Filter by product status
- in: query
name: price_min
schema:
type: number
description: Filter products with min_price >= value
- in: query
name: price_max
schema:
type: number
description: Filter products with max_price <= value
- in: query
name: sort
schema:
type: string
enum: [name, sku, price, brand, category, status, created_at, updated_at]
description: Sort field
- in: query
name: order
schema:
type: string
enum: [asc, desc]
default: asc
description: Sort direction
responses:
200:
description: Paginated product list
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/Product"
next_page:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
put:
summary: Upsert products (bulk)
operationId: bulkUpsertProducts
tags: [Products]
description: |
Create or update products by SKU (max 50 per call). For an SKU that already exists
this is a partial update: send only the fields you want to change — any field you
omit is left unchanged. `name` and `price` are required only when creating a new
SKU; once the product exists they are optional, but when supplied they cannot be
null or empty.
Note: Competitor Discovery is not triggered automatically when products are added
or updated through the API. Launch it from your Pricefy dashboard when you want to
find competitors for your catalog.
requestBody:
required: true
content:
application/json:
schema:
type: array
maxItems: 50
items:
$ref: '#/components/schemas/Product'
responses:
201:
description: Catalog updated successfully
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessfulOperation"
400:
description: Validation error, batch size exceeded, or read-only access
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
401:
$ref: "#/components/responses/Unauthorized"
/v1/merchant/products/{sku}:
parameters:
- name: sku
in: path
required: true
schema:
type: string
get:
summary: Get product
operationId: getProduct
tags: [Products]
responses:
200:
description: Product details with monitored URLs
content:
application/json:
schema:
$ref: "#/components/schemas/Product"
401:
$ref: "#/components/responses/Unauthorized"
404:
$ref: "#/components/responses/NotFound"
put:
summary: Upsert product
operationId: upsertProduct
tags: [Products]
description: |
Create or update a single product by SKU. For an existing product this is a partial
update: send only the fields you want to change — any field you omit is left
unchanged. `name` and `price` are required only when creating the product; on update
they are optional, but when supplied they cannot be null or empty.
Note: Competitor Discovery is not triggered automatically when a product is added
or updated through the API. Launch it from your Pricefy dashboard when you want to
find competitors for your catalog.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
responses:
201:
description: Product upserted
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessfulOperation"
400:
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
401:
$ref: "#/components/responses/Unauthorized"
delete:
summary: Delete product
operationId: deleteProduct
tags: [Products]
responses:
200:
description: Product deleted
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessfulOperation"
401:
$ref: "#/components/responses/Unauthorized"
404:
$ref: "#/components/responses/NotFound"
/v1/competitors:
get:
summary: List competitors
operationId: listCompetitors
tags: [Competitors]
description: |
Returns all competitors associated with the merchant, with aggregated price analysis.
Each competitor includes name, logo, counts of monitored/lower/higher/equal products, and MAP infringements.
Paginated (default 25 per page).
parameters:
- in: query
name: page
schema:
type: integer
default: 1
- in: query
name: limit
schema:
type: integer
default: 25
description: Results per page (max 100)
# v2.1.0 filters
- in: query
name: search
schema:
type: string
minLength: 3
description: Search by domain (LIKE)
- in: query
name: status
schema:
type: string
enum: [active, disabled]
description: Filter by competitor status
- in: query
name: sort
schema:
type: string
enum: [domain, monitored_products, status]
description: Sort field
- in: query
name: order
schema:
type: string
enum: [asc, desc]
default: asc
description: Sort direction
responses:
200:
description: Paginated competitor list with price analysis
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/Competitor"
next_page:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
post:
summary: Add competitor
operationId: addCompetitor
tags: [Competitors]
requestBody:
content:
application/json:
schema:
type: object
required: [url]
properties:
url:
type: string
format: uri
responses:
201:
description: Competitor added
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessfulOperation"
400:
description: Invalid URL, not profiled, or limit exceeded
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
401:
$ref: "#/components/responses/Unauthorized"
put:
summary: Update competitor status
operationId: updateCompetitorStatus
tags: [Competitors]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [url, status]
properties:
url:
type: string
format: uri
status:
type: string
enum: [active, disabled]
responses:
200:
description: Status updated
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessfulOperation"
400:
description: Invalid status or limit exceeded
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
401:
$ref: "#/components/responses/Unauthorized"
404:
$ref: "#/components/responses/NotFound"
/v1/competitors/{domain}:
parameters:
- name: domain
in: path
required: true
schema:
type: string
description: "Competitor domain (e.g. `amazon.it`, `ebay.com`)"
example: "amazon.it"
get:
summary: Get competitor
operationId: getCompetitor
tags: [Competitors]
description: Get details for a specific competitor by domain name, including price analysis stats.
responses:
200:
description: Competitor details with price analysis
content:
application/json:
schema:
$ref: "#/components/schemas/Competitor"
401:
$ref: "#/components/responses/Unauthorized"
404:
$ref: "#/components/responses/NotFound"
/v1/competitors/urls:
get:
summary: List monitored URLs
operationId: listMonitoredUrls
tags: [Monitored URLs]
description: |
Returns competitor product URLs being monitored, with price comparison data.
Includes full merchant product data (cost, min/max price, MAP, brand, category, stock, image, status)
and competitor data (price, domain, logo, stock, currency).
Supports advanced filtering by price position, stock, MAP infringement, and more.
parameters:
- in: query
name: limit
schema:
type: integer
default: 25
description: Results per page (max 100)
- in: query
name: page
schema:
type: integer
default: 1
- in: query
name: competitor_id
schema:
type: integer
- in: query
name: sku
schema:
type: string
- in: query
name: url
schema:
type: string
- in: query
name: last_analyzed_at
schema:
type: string
format: date-time
# v2.1.0 filters
- in: query
name: search
schema:
type: string
minLength: 3
description: Search by SKU, product name, or competitor URL
- in: query
name: brand
schema:
type: string
description: Filter by product brand
- in: query
name: status
schema:
type: string
enum: [enabled, disabled, in_progress, scraping_failed, not_found, missing_price]
description: Filter by URL monitoring status
- in: query
name: diff
schema:
type: string
enum: [lower, higher, equal]
description: "Price position: lower = merchant cheaper, higher = merchant more expensive"
- in: query
name: stock
schema:
type: string
enum: [in_stock, out_of_stock]
description: Filter by competitor stock
- in: query
name: map_infringement
schema:
type: string
enum: ["0", "1"]
description: "1 = competitor price below MAP"
- in: query
name: sort
schema:
type: string
enum: [competitor_domain, competitor_price, product_price, price_diff, percentage_diff, status, analyzed_at]
- in: query
name: order
schema:
type: string
enum: [asc, desc]
default: asc
responses:
200:
description: Paginated monitored URLs
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/CompetitorUrl"
next_page:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
put:
summary: Upsert monitored URLs
operationId: upsertMonitoredUrls
tags: [Monitored URLs]
requestBody:
required: true
content:
application/json:
schema:
type: array
maxItems: 50
items:
type: object
required: [merchant_product_sku, competitor_url, status]
properties:
merchant_product_sku:
type: string
competitor_url:
type: string
format: uri
status:
type: string
enum: [active, disabled]
price_adjuster_rule:
type: object
description: >-
Optional. Adjusts the competitor's scraped price before it is compared
with yours (for example to add local tax or shipping). When enabled, the
scraped price is recalculated using the chosen operator and value.
required: [enabled]
properties:
enabled:
type: boolean
description: Turn the adjustment on or off while keeping its configuration.
operator:
type: string
enum: [multiply, divide, add, subtract, percentage_add, percentage_subtract, add_vat, subtract_vat]
description: >-
How the value is applied. Use add_vat to add VAT at the given rate to
the scraped price, or subtract_vat to remove VAT and recover the net
price. Required when enabled is true.
value:
type: number
description: >-
The amount applied with the operator (for add_vat and subtract_vat it
is the VAT rate as a percentage). Must be greater than 0
(and below 100 for percentage_subtract). Required when enabled is true.
description:
type: string
maxLength: 500
description: >-
Optional note describing the adjustment
(for example "Pack of 6 — competitor sells single units").
responses:
200:
description: URLs updated
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessfulOperation"
400:
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
401:
$ref: "#/components/responses/Unauthorized"
402:
description: Monitored URLs limit exceeded (error_code 109)
content:
application/json:
schema:
$ref: "#/components/schemas/LimitExceededError"
delete:
summary: Delete monitored URLs
operationId: deleteMonitoredUrls
tags: [Monitored URLs]
requestBody:
content:
application/json:
schema:
type: array
maxItems: 50
items:
type: object
properties:
competitor_id:
type: integer
merchant_product_sku:
type: string
responses:
200:
description: URLs deleted
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessfulOperation"
400:
description: Batch size exceeded
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
401:
$ref: "#/components/responses/Unauthorized"
# v3.5.0 — price-history detail for one monitored URL (a SKU at one competitor)
/v1/competitors/urls/detail:
get:
summary: Monitored URL price-history detail
operationId: getMonitoredUrlDetail
tags: [Monitored URLs]
description: |
Price-history detail for a single monitored URL: one of your SKUs at one
competitor. Returns the competitor's daily price series over the requested
window (with your own price for each day), summary statistics
(low/high/average and the number of points) and the current price with its
delta versus your price. Powers the price chart on the product detail.
parameters:
- in: query
name: sku
required: true
schema:
type: string
description: Your product SKU.
- in: query
name: competitor_id
required: true
schema:
type: integer
description: The competitor the monitored URL belongs to.
- in: query
name: days
schema:
type: integer
default: 30
minimum: 1
maximum: 90
description: Size of the trailing window in days, ending today.
responses:
200:
description: Price-history detail
content:
application/json:
schema:
$ref: "#/components/schemas/MonitoredUrlDetail"
400:
description: Missing or invalid sku / competitor_id
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
401:
$ref: "#/components/responses/Unauthorized"
404:
$ref: "#/components/responses/NotFound"
/v1/map-infringements:
get:
summary: List MAP infringements
operationId: listMapInfringements
tags: [MAP Infringements]
description: |
Resellers selling below your Minimum Advertised Price. By default returns
the competitors that went below MAP in the last 7 days.
parameters:
- in: query
name: page
schema:
type: integer
default: 1
- in: query
name: limit
schema:
type: integer
default: 25
- in: query
name: direction
schema:
type: string
enum: [went_infringed, went_respected, all]
default: went_infringed
description: Infringements (went_infringed), back-in-compliance (went_respected) or both (all)
- in: query
name: competitor_id
schema:
type: integer
description: Filter by competitor
- in: query
name: period
schema:
type: integer
default: 7
description: Look-back window in days
- in: query
name: min_gap_pct
schema:
type: number
description: Only rows whose absolute gap from MAP is at least this percentage
- in: query
name: search
schema:
type: string
minLength: 3
description: Search by product SKU, product name or competitor domain
responses:
200:
description: Paginated MAP infringements
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/MapInfringement"
next_page:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
/v1/map-infringement-rules:
get:
summary: List MAP infringement rules
operationId: listMapInfringementRules
tags: [MAP Infringements]
description: |
Returns the Minimum Advertised Price rules configured by the merchant.
Each rule watches a set of competitors and flags resellers selling below MAP.
Active rules are listed first.
parameters:
- in: query
name: page
schema:
type: integer
default: 1
- in: query
name: limit
schema:
type: integer
default: 25
- in: query
name: search
schema:
type: string
minLength: 3
description: Search by rule name
- in: query
name: status
schema:
type: string
enum: [active, disabled]
responses:
200:
description: Paginated MAP infringement rules
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/MapInfringementRule"
next_page:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
/v1/dynamic-pricing/list:
get:
summary: List repricing rules
operationId: listRepricingRules
tags: [Repricing]
responses:
200:
description: Repricing rules
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/RepricingRule"
401:
$ref: "#/components/responses/Unauthorized"
# v2.1.0 — New endpoints
/v1/dynamic-pricing/preview:
get:
summary: Repricing preview
operationId: getRepricingPreview
tags: [Repricing]
description: |
Returns repricing results from the latest job execution of each rule.
Shows suggested, applied, skipped, and errored price changes with full margin calculations.
Results include error details from both the job and the apply process.
parameters:
- in: query
name: page
schema:
type: integer
default: 1
- in: query
name: limit
schema:
type: integer
default: 25
- in: query
name: rule_id
schema:
type: integer
description: Filter by repricing rule
- in: query
name: search
schema:
type: string
minLength: 3
description: Search by SKU, product name, or rule name
- in: query
name: status
schema:
type: string
enum: [suggested, skipped, repriced, error]
description: Filter by result status
- in: query
name: diff
schema:
type: string
enum: [lower, higher, equal]
description: Price position vs competitor
responses:
200:
description: Paginated repricing preview results
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/RepricingPreviewResult"
next_page:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
# v3.10.0 — Apply suggested repricing prices
/v1/dynamic-pricing/apply/{rule_id}:
post:
summary: Apply suggested prices
operationId: applyRepricing
tags: [Repricing]
description: |
Apply the suggested price to selected products (SKUs) of one repricing rule,
in bulk (up to 30 SKUs per call). Take the SKUs from the suggested results of
the repricing preview. This queues the price change: the response confirms the
request was accepted, and the final result is polled from the repricing preview
(each product moves from "suggested" to "repriced" or "error"). SKUs that are no
longer suggested are reported back as skipped. To apply across multiple rules or
more than 30 SKUs, send multiple requests.
parameters:
- in: path
name: rule_id
required: true
schema:
type: integer
description: The repricing rule id.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [skus]
properties:
skus:
type: array
minItems: 1
maxItems: 30
description: Up to 30 products to apply, taken from the suggested preview results.
items:
type: object
required: [sku]
properties:
sku:
type: string
description: The product SKU.
example:
skus:
- sku: "ABC-1"
- sku: "ABC-2"
responses:
202:
description: The repricing apply was accepted and queued.
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: success
message:
type: string
example: Repricing apply queued.
data:
type: object
properties:
rule_id:
type: integer
queued_skus:
type: array
items:
type: string
skipped_skus:
type: array
items:
type: object
properties:
sku:
type: string
reason:
type: string
example: not_suggested
400:
description: Invalid request, or none of the provided SKUs are currently suggested for this rule.
402:
description: Repricing apply limit reached for the current plan.
404:
description: Repricing rule not found.
409:
description: An apply is already running for this rule.
422:
description: Repricing is not available for this store platform.
401:
$ref: "#/components/responses/Unauthorized"
/v1/reports:
get:
summary: List reports
operationId: listReports
tags: [Reports]
description: |
Returns scheduled reports (catalog exports, competitor exports, etc.).
Includes computed `next_run_at` based on frequency and daily_time configuration.
Filter by status (SCHEDULED/RUNNING/COMPLETE/FAILED), frequency, or enabled flag.
parameters:
- in: query
name: page
schema:
type: integer
default: 1
- in: query
name: limit
schema:
type: integer
default: 25
- in: query
name: status
schema:
type: string
enum: [scheduled, running, complete, failed]
- in: query
name: frequency
schema:
type: string
enum: [hourly, daily, weekly]
- in: query
name: enabled
schema:
type: string
enum: ["0", "1"]
responses:
200:
description: Paginated report list
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/Report"
next_page:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
/v1/reports/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: integer
get:
summary: Get report
operationId: getReport
tags: [Reports]
responses:
200:
description: Report detail
content:
application/json:
schema:
$ref: "#/components/schemas/ReportDetail"
401:
$ref: "#/components/responses/Unauthorized"
404:
$ref: "#/components/responses/NotFound"
/v1/alert-rules:
get:
summary: List alert rules
operationId: listAlertRules
tags: [Alerts]
description: |
Returns alert rules configured by the merchant.
Each rule defines conditions (price/stock changes) that trigger notifications.
Includes competitor count, last notification date, and total alerts triggered.
parameters:
- in: query
name: page
schema:
type: integer
default: 1
- in: query
name: limit
schema:
type: integer
default: 25
- in: query
name: search
schema:
type: string
minLength: 3
description: Search by rule name
- in: query
name: status
schema:
type: string
enum: [active, disabled]
responses:
200:
description: Paginated alert rules
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/AlertRule"
next_page:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
/v1/alert-rules/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: integer
get:
summary: Get alert rule
operationId: getAlertRule
tags: [Alerts]
responses:
200:
description: Alert rule detail with competitor list
content:
application/json:
schema:
$ref: "#/components/schemas/AlertRuleDetail"
401:
$ref: "#/components/responses/Unauthorized"
404:
$ref: "#/components/responses/NotFound"
/v1/alert-rules/{id}/alerts:
parameters:
- name: id
in: path
required: true
schema:
type: integer
get:
summary: Get alert rule alerts
operationId: getAlertRuleAlerts
tags: [Alerts]
description: Returns alerts triggered by this rule from DynamoDB
parameters:
- in: query
name: last_sku
schema:
type: string
description: Cursor for pagination (last SKU from previous page)
- in: query
name: instant
schema:
type: string
enum: ["0", "1"]
default: "0"
description: Show instant alerts (prefix INSTANT- in DynamoDB)
responses:
200:
description: Alert results grouped by SKU
content:
application/json:
schema:
type: object
properties:
items:
type: object
description: |
Alerts grouped by product SKU. Each key is a SKU string, value is an object:
- `product_code`: string (nullable)
- `product_stock`: integer (nullable)
- `rule_name`: string — name of the alert rule
- `rule_alert_type`: string — rule key (e.g. "price", "stock")
- `child`: array of alert objects, each containing competitor_name, competitor_logo, competitor_url, price_change, price_change_percentage, price_change_fixed, merchant_variation_price, merchant_variation_previous_price, merchant_variation_stock, merchant_variation_previous_stock, variation_change_date
additionalProperties:
type: object
properties:
product_code:
type: string
nullable: true
product_stock:
type: integer
nullable: true
rule_name:
type: string
rule_alert_type:
type: string
child:
type: array
items:
type: object
page_size:
type: integer
first:
type: string
nullable: true
last:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
404:
$ref: "#/components/responses/NotFound"
/v1/alerts:
get:
summary: List alert variations
operationId: listAlerts
tags: [Alerts]
description: Price/stock variations from competitors (last 7 days)
parameters:
- in: query
name: page
schema:
type: integer
default: 1
- in: query
name: limit
schema:
type: integer
default: 25
- in: query
name: competitor_id
schema:
type: integer
description: Filter by competitor
responses:
200:
description: Paginated alert variations with product/competitor enrichment
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/AlertVariation"
next_page:
type: string
nullable: true
401:
$ref: "#/components/responses/Unauthorized"
/postman/collection.json:
get:
summary: Download the Postman collection
operationId: downloadPostmanCollection
tags: [Postman]
description: |
Returns the **complete Pricefy API as a Postman Collection v2.1** JSON file, mirroring [the public Pricefy Postman workspace](https://www.postman.com/pricefy/workspace/pricefy-api).
Two ways to use it:
1. **Open the workspace online** — click [](https://www.postman.com/pricefy/workspace/pricefy-api) to land in the live workspace and fork it into your own.
2. **Download this JSON** and import it manually (`File → Import → Upload Files` in Postman, or `newman run pricefy-api.postman_collection.json` for CI).
Set the `X-Api-Key` variable in the environment and you're ready to send requests.
The file is regenerated from `openapi.yaml` whenever a new version of the API is released.
responses:
200:
description: Postman Collection v2.1 JSON
content:
application/json:
schema:
type: object
description: Postman Collection v2.1 schema (see https://schema.postman.com/collection/json/v2.1.0/draft-07/collection.json)
404:
description: Collection file not deployed (should not happen in production)
security: []
/mcp:
post:
summary: MCP server (Streamable HTTP JSON-RPC)
operationId: mcpServer
tags: [MCP]
security:
- ApiKey: []
- OAuth2: [mcp:use]
description: |
**Model Context Protocol** endpoint. Speaks JSON-RPC 2.0 over HTTP (Streamable HTTP transport, MCP spec 2025-11-25).
**Two authentication options**:
- `X-Api-Key: ` — same header as the REST API. Use this with Claude Desktop, Cursor, Codex, and any client that supports custom headers.
- `Authorization: Bearer ` — OAuth, used by ChatGPT custom connectors. Set it up from the connector dialog: see the **MCP support** section on the main page for the step-by-step guide.
Permissions are enforced on every tool call — an authorization granted as read-only can never invoke destructive tools, regardless of how it was issued.
**Setup snippets**: see the introduction at the top of this page.
**Available tools (25)**
Read-only (18):
`get_account`, `get_store`, `list_products`, `get_product`,
`list_competitors`, `get_competitor`, `list_monitored_urls`, `get_monitored_url_detail`,
`list_repricing_rules`, `get_repricing_preview`,
`list_reports`, `get_report`,
`list_alerts`, `list_alert_rules`, `get_alert_rule`, `get_alerts_for_rule`,
`list_map_infringements`, `list_map_infringement_rules`.
Write (5):
`upsert_product`, `bulk_upsert_products`, `add_competitor`,
`update_competitor_status`, `batch_upsert_monitored_urls`.
Destructive (2, require client confirmation):
`delete_product`, `batch_delete_monitored_urls`.
**Discovery via JSON-RPC**:
- `initialize` — handshake (returns the `MCP-Session-Id` header)
- `tools/list` — full tool catalog with input schemas
- `tools/call` — invoke a tool by name with arguments
requestBody:
required: true
content:
application/json:
schema:
type: object
description: JSON-RPC 2.0 envelope
properties:
jsonrpc:
type: string
example: "2.0"
id:
type: integer
example: 1
method:
type: string
description: One of `initialize`, `tools/list`, `tools/call`
example: "tools/list"
params:
type: object
examples:
initialize:
summary: Handshake
value:
jsonrpc: "2.0"
id: 1
method: "initialize"
params:
protocolVersion: "2025-06-18"
capabilities: {}
clientInfo:
name: "curl"
version: "1"
listTools:
summary: List available tools
value:
jsonrpc: "2.0"
id: 2
method: "tools/list"
callListProducts:
summary: Invoke list_products
value:
jsonrpc: "2.0"
id: 3
method: "tools/call"
params:
name: "list_products"
arguments:
limit: 10
sort: "price"
order: "desc"
parameters:
- in: header
name: Accept
required: true
schema:
type: string
enum: ["application/json, text/event-stream"]
- in: header
name: MCP-Session-Id
required: false
schema:
type: string
description: Returned by `initialize`, required on every subsequent call.
responses:
200:
description: JSON-RPC response
content:
application/json:
schema:
type: object
properties:
jsonrpc:
type: string
example: "2.0"
id:
type: integer
result:
type: object
401:
$ref: "#/components/responses/Unauthorized"
403:
description: Forbidden — the API key does not have permission for the invoked tool's group+method
components:
responses:
Unauthorized:
description: Unauthorized — missing or invalid API key
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
schemas:
Account:
type: object
properties:
account_type:
type: string
enum: [MERCHANT, BRAND]
description: Drives the app's mode — BRAND switches dashboard, Competitors→Resellers and Movers→MAP.
subscription_type:
type: string
description: Plan code (e.g. "free", "business")
subscription_name:
type: string
description: Human-readable plan name (e.g. "Business")
subscription_status:
type: string
description: One of active, trialing, past_due, unpaid, inactive
subscription_started_at:
type: string
format: date-time
products_limit:
type: integer
description: Effective product import limit (plan + override + additional)
competitors_nominal_limit:
type: string
nullable: true
competitors_limit:
type: integer
description: Effective competitor limit (plan + override)
# v2.3.0 — Effective plan limits vector
plan_limits:
type: object
description: |
Effective plan limits with override, addon and additional_* applied.
Single source of truth for what the merchant is actually allowed to do.
properties:
import_limit_product:
type: integer
competitor_limit:
type: integer
max_monitored_urls:
type: integer
limit_automatch:
type: integer
edit_additional_email_for_alerts:
type: boolean
limit_additional_email_for_alerts:
type: integer
rate_limit:
type: integer
description: API rate limit (requests/min)
has_override:
type: boolean
description: True if max_monitored_urls comes from billing_profile_override
base_monitored_urls:
type: integer
description: Plan/override base before addon stack
addon_monitored_urls:
type: integer
description: Active paid addon contribution
addon_quantity:
type: integer
merchant:
type: object
properties:
name: { type: string, nullable: true }
surname: { type: string, nullable: true }
company_name: { type: string, nullable: true }
email: { type: string, nullable: true }
currency_code: { type: string, nullable: true }
usage:
type: object
description: Current usage vs limits, mirroring the web /account/usage page.
properties:
products: { type: integer }
competitors: { type: integer }
monitored_urls: { type: integer }
automatch_requests: { type: integer }
automatch_limit: { type: integer, nullable: true }
single_discovery_used: { type: integer }
single_discovery_daily_limit: { type: integer }
Store:
type: object
properties:
platform:
type: string
nullable: true
description: Raw platform code (e.g. shopify, woocommerce, external_data_feed); null if none.
platform_label:
type: string
nullable: true
description: Display label (Shopify, WooCommerce, CSV, Google Shopping…); null if no feed.
platform_icon:
type: string
nullable: true
description: Stable icon slug for the platform logo (shopify, woocommerce, magento, prestashop, bigcommerce, google, csv…); null when no known logo.
store_url:
type: string
nullable: true
feed_connected:
type: boolean
description: Whether a product feed has completed an import.
added_at:
type: string
format: date-time
nullable: true
last_import:
type: string
format: date-time
nullable: true
last_imported_products:
type: integer
Product:
type: object
description: |
Product from the merchant's catalog.
- When **reading** (GET), `status` is returned as `active` or `inactive`.
- When **writing** (PUT upsert), `status` accepts `active` or `disabled`.
- Numeric fields (`cost`, `price`, `min_price`, `max_price`, `map`) must be sent as
numbers using a dot as the decimal separator, e.g. `1079.50` — a comma
(`1079,50`) or any non-numeric value is rejected with a 400 validation error.
- `GET /v1/merchant/products/{sku}` includes an additional `monitored_urls` array.
properties:
id:
type: integer
sku:
type: string
name:
type: string
brand:
type: string
category:
type: string
code:
type: string
description: GTIN/barcode
picture_url:
type: string
product_url:
type: string
description: URL of the product page on the merchant store
cost:
type: number
price:
type: number
min_price:
type: number
max_price:
type: number
map:
type: number
description: Minimum Advertised Price
status:
type: string
description: "GET returns `active`/`inactive`. PUT accepts `active`/`disabled`."
count_competitor_urls:
type: integer
description: "Number of monitored competitor URLs for this product (only in list endpoint)"
count_suggested_urls:
type: integer
description: "Number of pending automatch URL suggestions (only in list endpoint)"
tags:
type: array
description: "Tag names assigned to the product (empty array when the product has no tags)."
items:
type: string
additional_fields:
type: object
writeOnly: true
description: >
Optional map of extra fields from your source platform (key → value) kept
alongside the product. Send it on a PUT upsert to store or update those
values; set a value to null or an empty string to remove that key. Values
are stored as text (numbers and true/false are accepted and converted).
Write-only: not returned in product GET responses.
additionalProperties:
type: string
monitored_urls:
type: array
description: "Only returned in GET /v1/merchant/products/{sku} (product detail)"
items:
type: object
properties:
id:
type: integer
competitor_url:
type: string
price:
type: number
status:
type: string
enum: [Disabled, Enabled, In Progress, Scraping Failed, Not Found, Missing Price]
error_status_code:
type: string
scheduled_at:
type: string
format: date-time
analyzed_at:
type: string
format: date-time
title:
type: string
competitor_id:
type: integer
qty:
type: integer
brand:
type: string
picture_url:
type: string
code:
type: string
RepricingRule:
type: object
properties:
id:
type: integer
name:
type: string
automatic:
type: string
enum: [automatic, semi-automatic]
status:
type: string
enum: [Active, Disabled]
all_competitors:
type: integer
enum: [0, 1]
description: 1 = the rule applies to all competitors (per-rule count is 0)
competitors:
type: integer
job_status:
type: string
last_runned:
type: string
format: date-time
nullable: true
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
# v2.1.0
RepricingPreviewResult:
type: object
properties:
result_id:
type: integer
sku:
type: string
product_name:
type: string
product_image:
type: string
product_url:
type: string
product_code:
type: string
rule_id:
type: integer
rule_name:
type: string
rule_json:
type: string
description: JSON rule configuration
merchant_price:
type: number
merchant_cost:
type: number
competitor_price:
type: number
repriced_price:
type: number
adjusted_repriced_price:
type: number
highest_competitor_price:
type: number
highest_competitor_id:
type: integer
cheapest_competitor_price:
type: number
cheapest_competitor_id:
type: integer
avg_competitor_price:
type: number
merchant_min_price:
type: number
merchant_max_price:
type: number
status:
type: integer
description: "Result status: 1=suggested, 2=processing, 3=applied, 4=rejected, 5=skipped"
status_code:
type: string
nullable: true
description: Machine-readable status code (e.g. BELOW_MIN_PRICE, ABOVE_MAX_PRICE)
applied_status:
type: integer
description: "Apply status: 0=not applied, 1=repriced (applied successfully), 2=pending, 3=error"
applied_at:
type: string
format: date-time
nullable: true
merchant_gross_margin:
type: number
merchant_gross_margin_perc:
type: number
error_message:
type: string
nullable: true
apply_error_info:
type: string
nullable: true
result_updated_at:
type: string
format: date-time
Competitor:
type: object
properties:
id:
type: integer
domain:
type: string
description: Competitor domain (e.g. amazon.it)
competitor_name:
type: string
description: Display name (falls back to domain if name is null)
logo:
type: string
nullable: true
description: URL of competitor logo
status:
type: integer
enum: [0, 1]
description: Per-merchant tracking switch. 1 = enabled, 0 = disabled (disabled takes priority over `ready_to_analyze` when labelling).
ready_to_analyze:
type: integer
enum: [0, 1, 2, 3]
description: Profiling state when enabled. 1 = active, 0 = needs profile update, 2 = suspended, 3 = profiling in progress.
monitored_products:
type: integer
description: Number of monitored product URLs for this competitor
lower_products:
type: integer
description: Products where merchant price is lower than competitor
higher_products:
type: integer
description: Products where merchant price is higher than competitor
equal_products:
type: integer
description: Products where prices are equal
map_infringements:
type: integer
description: Products where competitor price is below MAP (Minimum Advertised Price)
count_suggested_urls:
type: integer
description: Number of pending URL suggestions from automatch (not yet approved)
price_adjuster:
type: object
description: >-
General price adjustment configured for this competitor. It applies to every
monitored URL of the competitor and recalculates its prices before they are
compared with yours (a per-URL rule, when set, is applied on top of it).
properties:
enabled:
type: boolean
description: True when the general price adjustment is active (turned on and with a non-zero value).
mode:
type: string
nullable: true
enum: [plus, minus, divided, multiplied, add_vat, subtract_vat]
description: The operation applied to the competitor price.
value:
type: number
nullable: true
description: The adjustment amount; the mode decides how it is applied.
type:
type: string
nullable: true
enum: [percentage, fixed]
description: Whether the value is a percentage or a fixed amount (VAT modes are always percentage).
CompetitorUrl:
type: object
properties:
id:
type: integer
competitor_id:
type: integer
competitor_domain:
type: string
competitor_logo:
type: string
nullable: true
competitor_product_title:
type: string
description: Title of the competitor product page
competitor_product_image:
type: string
description: Image URL from competitor product page
competitor_product_code:
type: string
description: GTIN/barcode from competitor
competitor_brand:
type: string
description: Brand from competitor product page
competitor_price:
type: number
description: Competitor product price
product_price:
type: number
description: Merchant's own product price
price_diff:
type: number
nullable: true
percentage_diff:
type: number
nullable: true
map_infringement:
type: integer
enum: [0, 1]
currency_code:
type: string
nullable: true
status:
type: string
enum: [Disabled, Enabled, In Progress, Scraping Failed, Not Found, Missing Price]
error_status_code:
type: string
competitor_url:
type: string
variant_list:
type: array
nullable: true
description: Variant data extracted from competitor product (sizes, colors, etc.)
items:
type: object
price_adjuster_rule:
type: object
nullable: true
description: >-
Optional per-URL price scaling applied to the competitor's scraped price before it
is compared with yours. Null when no rule is configured.
properties:
enabled:
type: boolean
operator:
type: string
enum: [multiply, divide, add, subtract, percentage_add, percentage_subtract, add_vat, subtract_vat]
value:
type: number
nullable: true
description:
type: string
nullable: true
has_price_adjustment:
type: integer
enum: [0, 1]
description: >-
1 when a general, account-wide price adjustment is active for this competitor,
so the competitor prices shown here are already recalculated with it. This general
adjustment applies first; the optional per-URL price_adjuster_rule is applied on top.
0 when no general adjustment is active.
competitor_stock:
type: integer
nullable: true
description: Stock quantity from competitor
merchant_product_sku:
type: string
merchant_product_code:
type: string
merchant_product_url:
type: string
merchant_product_title:
type: string
# v2.1.0 A4 columns
product_cost:
type: number
nullable: true
product_min_price:
type: number
nullable: true
product_max_price:
type: number
nullable: true
product_map:
type: number
nullable: true
product_brand:
type: string
nullable: true
product_category:
type: string
nullable: true
product_stock:
type: integer
nullable: true
product_image:
type: string
nullable: true
product_status:
type: string
enum: [active, inactive]
analyzed_at:
type: string
format: date-time
scheduled_at:
type: string
format: date-time
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
# v3.5.0
MonitoredUrlDetail:
type: object
properties:
product:
type: object
properties:
sku:
type: string
title:
type: string
nullable: true
brand:
type: string
nullable: true
code:
type: string
nullable: true
description: GTIN/barcode.
image_url:
type: string
nullable: true
competitor:
type: object
properties:
id:
type: integer
domain:
type: string
logo:
type: string
nullable: true
url:
type: string
description: The monitored competitor product URL.
currency_code:
type: string
description: ISO currency code of the prices (defaults to EUR).
range:
type: object
properties:
date_start:
type: string
format: date
date_end:
type: string
format: date
days:
type: integer
current:
type: object
properties:
competitor_price:
type: number
nullable: true
my_price:
type: number
nullable: true
diff:
type: number
nullable: true
description: my_price − competitor_price.
diff_percentage:
type: number
nullable: true
stats:
type: object
description: Computed over the competitor price points in the window.
properties:
low:
type: number
nullable: true
high:
type: number
nullable: true
average:
type: number
nullable: true
changes:
type: integer
description: Number of days that have a competitor price.
series:
type: array
description: One entry per day with a competitor price, oldest first.
items:
type: object
properties:
date:
type: string
format: date
competitor_price:
type: number
my_price:
type: number
nullable: true
description: Your price that day (last-known carried forward).
# v2.1.0
Report:
type: object
properties:
id:
type: integer
name:
type: string
internal_id:
type: string
frequency:
type: string
enum: [DAILY, WEEKLY, HOURLY]
enabled:
type: integer
status:
type: string
enum: [SCHEDULED, RUNNING, COMPLETE, FAILED]
report_type:
type: string
description: Report type identifier (filter_url)
created_by:
type: integer
format:
type: string
enum: [csv, xlsx, pdf]
next_run_at:
type: string
format: date-time
nullable: true
scheduled_at:
type: string
format: date-time
nullable: true
started_at:
type: string
format: date-time
nullable: true
finished_at:
type: string
format: date-time
nullable: true
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
ReportDetail:
allOf:
- $ref: "#/components/schemas/Report"
- type: object
properties:
report_params:
type: object
description: Report parameters (format, daily_time, communications)
filter_params:
type: object
nullable: true
description: Filters applied to this report
AlertRule:
type: object
properties:
rule_id:
type: integer
rule_name:
type: string
rules:
type: object
description: Alert rule configuration
rule_status:
type: integer
rule_notifications:
type: object
alert_type:
type: string
enum: [INSTANT, DAILY, ALL]
all_competitors:
type: integer
enum: [0, 1]
latest_total_alerts:
type: integer
competitors:
type: integer
description: Number of associated competitors
last_notified_at:
type: string
format: date-time
nullable: true
updated_at:
type: string
format: date-time
created_at:
type: string
format: date-time
AlertRuleDetail:
allOf:
- $ref: "#/components/schemas/AlertRule"
- type: object
properties:
competitor_list:
type: array
items:
type: object
properties:
id:
type: integer
domain:
type: string
logo:
type: string
nullable: true
MapInfringement:
type: object
description: A reseller selling below (or back above) your Minimum Advertised Price.
properties:
id:
type: integer
product_sku:
type: string
product_name:
type: string
nullable: true
product_image:
type: string
nullable: true
product_code:
type: string
nullable: true
competitor_id:
type: integer
competitor_domain:
type: string
nullable: true
competitor_logo:
type: string
nullable: true
competitor_url:
type: string
nullable: true
map:
type: number
description: Your minimum advertised price
competitor_price:
type: number
description: Competitor price after the change
competitor_previous_price:
type: number
description: Competitor price before the change
gap_pct:
type: number
description: Percentage gap from MAP (negative when below MAP)
currency_code:
type: string
description: Merchant currency (ISO 4217)
direction:
type: string
enum: [went_infringed, went_respected]
detected_at:
type: string
format: date-time
MapInfringementRule:
type: object
properties:
rule_id:
type: integer
rule_name:
type: string
rules:
type: object
description: MAP rule configuration (direction, competitor filters, thresholds)
rule_status:
type: integer
enum: [0, 1]
description: 1 = active, 0 = disabled
rule_notifications:
type: object
rule_type:
type: string
enum: [DAILY, WEEKLY, MONTHLY]
all_competitors:
type: integer
enum: [0, 1]
latest_total_alerts:
type: integer
job_status:
type: string
competitors:
type: integer
description: Number of associated competitors
updated_at:
type: string
format: date-time
created_at:
type: string
format: date-time
AlertVariation:
type: object
description: A price or stock variation detected from a competitor (last 7 days)
properties:
id:
type: integer
competitor_id:
type: integer
competitor_url:
type: string
competitor_price:
type: number
description: Current competitor price after the variation
competitor_previous_price:
type: number
description: Competitor price before the variation
price_change:
type: number
description: Price difference (current - previous)
competitor_stock:
type: integer
description: Current competitor stock after the variation
competitor_previous_stock:
type: integer
description: Competitor stock before the variation
variation_date:
type: string
format: date-time
product_sku:
type: string
nullable: true
product_name:
type: string
nullable: true
product_image:
type: string
nullable: true
product_price:
type: number
nullable: true
description: Merchant's own product price (for context)
competitor_domain:
type: string
nullable: true
competitor_logo:
type: string
nullable: true
SuccessfulOperation:
type: object
properties:
status:
type: string
data:
type: object
nullable: true
message:
type: string
Error:
type: object
properties:
status:
type: string
data:
type: object
message:
type: string
LimitExceededError:
type: object
properties:
status:
type: string
data:
type: object
properties:
error_code:
type: integer
example: 109
message:
type: string
securitySchemes:
ApiKey:
type: apiKey
in: header
name: X-Api-Key
OAuth2:
type: oauth2
description: |
Used by MCP clients that can't set a custom header, such as
ChatGPT custom connectors. To set it up, follow the
**Connect ChatGPT custom connector** guide on the main page —
the AI client handles the entire sign-in / consent flow for you.
flows:
authorizationCode:
authorizationUrl: https://api.pricefy.io/oauth/authorize
tokenUrl: https://api.pricefy.io/oauth/token
refreshUrl: https://api.pricefy.io/oauth/token
scopes:
mcp:use: Use the Pricefy MCP server (per-permission granularity chosen on the consent screen)
security:
- ApiKey: []
```