# Competitor Price Tracking API - Daily Price and Stock History (`nabeelbaghoor/competitor-price-history-api`) Actor

Competitor price tracking for your own products: daily price history with every competitor domain's price and stock status, your own price and price position, cheapest competitor and price gap, plus product feed settings, from the PriceShape REST API. Read only. Bring your own key.

- **URL**: https://apify.com/nabeelbaghoor/competitor-price-history-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** E-commerce, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$8.00 / 1,000 price history record returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Competitor Price Tracking API - Daily Price and Stock History

Export the daily competitor price and stock history your pricing account already tracks: one row per product per day with your own price, your price position and every competitor domain's price and stock, ready for a warehouse, a spreadsheet or a repricing rule.

### What it collects

- **Competitor price and stock history**: for each product you give (by UPI), every day in the period with your own sales price including and excluding VAT, your price position among competitors, and each matched competitor domain's scraped price, currency, stock status and the time that price or stock last changed.
- **Computed on every row**: number of competitors, number in stock, cheapest competitor domain and price, highest competitor price, and your price gap to the cheapest competitor in percent.
- **Two granularities**: one row per product per day with competitors nested, or one flat row per competitor price per day for charting.
- **Product feeds**: every feed your token can read, with its feed id, name, region, currency, UPI type (GTIN, SKU, MPN, id or URL), VAT settings, marketplace, variant options and import times. Any password or token embedded in a feed's source URL is removed before the row is written.
- **Filters**: date range and timezone sent to the provider, plus competitor domain and in-stock filters applied to the answer.
- Read only, pay per result, bring your own key.

### Input

| Field | What it does |
| --- | --- |
| What to read | Product feeds (default, needs nothing else), competitor price and stock history, or one product feed by id. |
| Product UPIs or feed ids | One per line. Product UPIs for price history, feed ids for one product feed. |
| Feed id | Price history: the feed the products belong to. Required there. |
| From date / To date | Price history: the period, as YYYY-MM-DD. Defaults to the provider's own window. |
| Timezone | Price history: IANA timezone of the period. |
| One row per | Price history: product per day, or competitor price per day. |
| Only these competitor domains | Price history: keep only these competitor domains. |
| Competitors in stock only | Price history: keep only in-stock competitor prices. |
| Draft feeds | Product feeds: active feeds or draft feeds. |
| Maximum results | Row cap for the run. |
| Requests per minute | Pacing for calls to the provider. |
| API token | Your own token, as a secret input. |
| API version | The X-API-Version header, 2026-02 by default. |

### FAQ

#### What is a competitor price tracking API used for?

Getting competitor prices out of a pricing tool and into the systems that act on them. An ecommerce pricing team loads yesterday's history for its whole catalogue into BigQuery or Snowflake each morning and tracks its price gap to the cheapest shop per product. A category manager charts one product's price against Amazon, Zalando or a local competitor over 90 days. A merchandiser checks which competitors went out of stock on a best seller before raising its price. A repricing script reads the cheapest in-stock competitor per product.

#### Which data source does this actor read?

The PriceShape REST API at api.priceshape.io, through the three read routes documented publicly at docs.priceshape.io: List feeds (`GET /feeds`), Get a feed (`GET /feeds/{priceshapeId}`) and Get product history (`GET /products/history/{upi}`). It reads the products and competitor matches already set up in your own account; it does not add products, find new competitors or trigger scrapes.

#### Do I need an API key?

Yes. This actor is bring-your-own-key and never ships one. Generate an API token under account settings on the API page of your provider portal, with read permission for feeds and for products, and paste it into the input or set it once as the `DATA_API_KEY` environment secret. A missing token, a refused token or a token without the needed permission ends the run cleanly with a message saying which it was.

#### How do I find the feed id and product UPIs?

Run the product feeds service first. Each feed row carries its feed id (`feedId`, the provider's priceshapeId) and its UPI type, which tells you whether products are identified by GTIN, SKU, MPN, your own id or product URL. Put that feed id in the feed id input and the product identifiers of that type in the identifiers input.

#### What does price position mean?

It is the provider's rank of your own price among the matched competitors for that product on that day. It is empty when no competitor was matched. The price gap column is computed here: your price including VAT minus the cheapest competitor price, as a percentage of that competitor price, so a positive number means you are more expensive.

#### What happens when there is nothing for a product or feed id?

It becomes its own row with `found: false` and a note: a product the feed does not know, a feed id the token cannot see, or a date range with no history. Those rows are never charged.

#### Can this actor change anything in my account?

No. Every request is a GET. The provider also documents a route that updates product fields, and it is not wired anywhere in this actor. The token is sent as a bearer header and never appears in a row or in the log.

#### How is it priced?

Pay per result: one flat price per record returned, whether a product day, a competitor price or a feed. Rows for products or ids that produced nothing, and competitor prices dropped by your filters, are free. Your provider subscription applies separately.

### Example output

```json
{
  "service": "productHistory",
  "serviceLabel": "Competitor price and stock history",
  "requested": "5701234567890",
  "found": true,
  "feedId": "6201ab9c3e2348ae8072c608cab91e29",
  "date": "2026-09-25",
  "upi": "5701234567890",
  "productId": "SHOE-1042",
  "gtin": "5701234567890",
  "sku": "SHOE-1042",
  "productUrl": "https://shop.example.com/products/running-shoe-1042",
  "currency": "DKK",
  "ownPriceInclVat": 899,
  "ownPriceExclVat": 719.2,
  "pricePosition": 3,
  "vendorCount": 4,
  "inStockVendorCount": 3,
  "cheapestVendorDomain": "competitor-one.dk",
  "cheapestVendorPrice": 849,
  "highestVendorPrice": 999,
  "priceGapPercent": 5.89,
  "vendors": [
    { "domain": "competitor-one.dk", "price": 849, "stockStatus": "In stock", "inStock": true, "currency": "DKK", "lastChangedAt": "2026-09-24T06:10:00.000Z" },
    { "domain": "competitor-two.dk", "price": 879, "stockStatus": "Out of stock", "inStock": false, "currency": "DKK", "lastChangedAt": "2026-09-20T04:55:00.000Z" }
  ],
  "retrievedAt": "2026-09-26T09:14:52.118Z",
  "note": null
}
```

Values are illustrative; every source field is one the provider documents.

### Keyword map

competitor price tracking API, competitor price monitoring, price history API, ecommerce price intelligence, competitor stock monitoring, price position, price gap analysis, dynamic pricing data, repricing data feed, product feed API, GTIN price lookup, retail price comparison data, PriceShape API.

# Actor input Schema

## `service` (type: `string`):

Product feeds lists every feed your token can read and needs nothing else, which is where the feed id for price history comes from, so it is the default. Competitor price and stock history reads, per product and per day, your own price beside every competitor domain's price and stock. One product feed reads the settings of the feed ids you give.

## `identifiers` (type: `array`):

One per line. For price history, the UPI (Unique Product Identifier) of each product, which is the GTIN, SKU, MPN, id or URL depending on the feed's UPI type shown by the product feeds service. For one product feed, the feed's priceshapeId. The product feeds service reads none.

## `feedId` (type: `string`):

Price history only, and required there: the priceshapeId of the feed the products belong to, as listed by the product feeds service.

## `fromDate` (type: `string`):

Price history only: the first day of the period, as YYYY-MM-DD. Left blank, the provider uses its own default window of roughly the last 90 days.

## `toDate` (type: `string`):

Price history only: the last day of the period, as YYYY-MM-DD. Left blank, the provider uses today.

## `timezone` (type: `string`):

Price history only: the IANA timezone the period is read in, such as Europe/Copenhagen or UTC. Left blank, the provider uses your account's timezone, otherwise UTC.

## `rowPer` (type: `string`):

Price history only. Product per day gives one row per product and date with every competitor price nested under vendors and the cheapest competitor and price gap computed. Competitor price per day gives one flat row per competitor domain per product and date, which is easier to chart or load into a spreadsheet.

## `vendorDomains` (type: `array`):

Price history only: keep only competitors whose domain is listed, one per line, such as amazon.de. Applied to the provider's answer; a product day with none of these competitors is left out.

## `inStockOnly` (type: `boolean`):

Price history only: keep only competitor prices whose stock status reads as in stock. Applied to the provider's answer.

## `draft` (type: `string`):

Product feeds only: the provider's draft parameter. False, its default, reads active feeds; true asks for draft feeds, which are inactive and receive no imports.

## `maxResults` (type: `integer`):

Stop after this many rows. A year of daily history for one product is up to 365 rows, or several times that with one row per competitor price.

## `requestsPerMinute` (type: `integer`):

Pacing ceiling for calls to the provider. Rate limited answers are retried after a pause.

## `apiKey` (type: `string`):

Your own API token, generated under account settings in your provider portal, with read access to feeds and to products. This actor is bring-your-own-key and never ships one. Leave blank to use the DATA\_API\_KEY environment secret instead. It is sent as a bearer token and never written to a row or the log.

## `apiVersion` (type: `string`):

The value of the X-API-Version header every request must carry. The provider names versions by release month.

## `baseUrl` (type: `string`):

Override the host the actor calls. Only useful for testing against a different environment.

## Actor input object example

```json
{
  "service": "feeds",
  "rowPer": "productDay",
  "inStockOnly": false,
  "draft": "false",
  "maxResults": 1000,
  "requestsPerMinute": 60,
  "apiVersion": "2026-02"
}
```

# Actor output Schema

## `records` (type: `string`):

One row per product and day, per competitor price, or per feed, alongside the identifier that produced it.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/competitor-price-history-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/competitor-price-history-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call nabeelbaghoor/competitor-price-history-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/competitor-price-history-api"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/DtaeclE6Ah9I02fjB/builds/vg9JHhDFG2r1LdTK7/openapi.json
