API-Referenz
Jeder Endpunkt der Daten-API, erzeugt aus ihrem OpenAPI-Dokument (Beschreibungen auf Englisch). Jede Antwort ist JSON, wenn nichts anderes dasteht.
- Basis-URL
https://pricana.io/api/v1- Anmeldung
- Your API key as a bearer token:
Authorization: Bearer prc_live_…. Live keys read your datasets, test keys only the sample datasets. Create keys in the portal (API). - OpenAPI-Dokument
- OpenAPI 3.1.0 (Pricana Data API v1)
Die Anfragen gehen mit Ihrem Key an diesen Server. Der Key bleibt nur im Speicher dieser Seite.
Datasets
What you can read: your datasets and the values to filter them by.
GET /api/v1/datasets
Your datasets
The datasets your plan lets you read, with how many items and websites each has and when its sources were last read. Their id is the dataset filter of the other requests.
Antworten
- 200 Your datasets.
application/jsonDataset[] - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
[
{
"description": "Laptops and notebooks from shops in Germany, Austria and Switzerland.",
"healthyModels": 14,
"id": 12,
"items": 18342,
"models": 14,
"name": "Laptops DACH",
"newestScrapeAt": "2026-10-07T09:12:00Z",
"oldestScrapeAt": "2026-10-07T05:40:00Z",
"sites": 9
}
]curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/datasets"Ausprobieren
GET /api/v1/facets
Websites, categories and currencies to filter by
The values the items can be filtered by, each with the number of items listed now.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
datasetquery | integer | One of your datasets (its id from /datasets); without it, all of them.Beispiel: 12 |
Antworten
- 200 The facets.
application/jsonFacets - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 404 No such dataset of yours.
application/jsonError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
{
"categories": [
{
"id": 8,
"items": 1804,
"name": "Laptops",
"parentId": 2,
"path": "Computers > Laptops",
"slug": "computers-laptops"
}
],
"currencies": [
{
"code": "EUR",
"items": 17920
}
],
"sites": [
{
"host": "www.notebookshop.example",
"id": 4,
"items": 2310,
"name": "Notebookshop"
}
]
}curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/facets"Ausprobieren
Items
Listings as they are now, and their history.
GET /api/v1/items
Find items
Items of your datasets, filtered and sorted, a page at a time (up to 500). To keep a copy in sync, use the change feed (/changes) or changedSince.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
datasetquery | integer | One of your datasets (its id from /datasets); without it, all of them.Beispiel: 12 |
sitequery | integer | Only items of this website (id from /facets).Beispiel: 4 |
categoryquery | string | A category's slug (from /facets), with its subcategories.Beispiel: computers-laptops |
qquery | string | Words to look for (all of them, in any order) in the title, brand, codes and other values of the item; parts of words count. Beispiel: thinkpad x1 |
minPricequery | number | Lowest price, in the item's currency. Beispiel: 500 |
maxPricequery | number | Highest price, in the item's currency. Beispiel: 1500 |
currencyquery | string | ISO 4217 code. Beispiel: EUR |
statusquery | string, einer von active, removed, all | active (listed now, the default), removed (no longer listed) or all. |
changedSincequery | string (date-time) | Only items with a change after this time (ISO 8601), e.g. the start of your last sync. Beispiel: 2026-10-01T00:00:00Z |
gtinquery | string | EAN/UPC/ISBN-13: the same product in every shop (leading zeros may be left out). Beispiel: 0196802123456 |
sortquery | string, einer von price, -price, -lastChanged, -lastSeen, -firstSeen, title | price, -price (highest first), -lastChanged (the default), -lastSeen, -firstSeen (newest listings first) or title. |
pagequery | integer | The page, from 0. Beispiel: 0Standard: 0 |
sizequery | integer | Items per page, 1 to 500. Beispiel: 100Standard: 50 |
Antworten
- 200 A page of items.
application/jsonPageDtoItem - 400 A parameter is not valid;
messagesays which.application/jsonError - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
{
"content": [
{
"attributes": {
"availability": "in stock",
"shipping": 0
},
"brand": "Lenovo",
"category": {
"name": null,
"path": null,
"slug": null,
"source": null
},
"currency": "EUR",
"datasets": [
"Laptops DACH"
],
"firstSeenAt": "2026-09-01T10:00:00Z",
"gtin": "0196802123456",
"id": 77,
"image": "https://www.notebookshop.example/img/thinkpad-x1.jpg",
"lastChangedAt": "2026-10-06T21:03:00Z",
"lastSeenAt": "2026-10-07T09:12:00Z",
"mpn": "21KC004MGE",
"previousPrice": 1499,
"price": 1399,
"priceChangedAt": "2026-10-06T21:03:00Z",
"removedAt": "2026-10-07T03:30:00Z",
"site": {
"attribution": null,
"host": null,
"id": null,
"name": null
},
"source": {
"modelId": null,
"name": null
},
"title": "Lenovo ThinkPad X1 Carbon Gen 12",
"url": "https://www.notebookshop.example/p/thinkpad-x1"
}
],
"page": 0,
"size": 50,
"totalElements": 1804,
"totalPages": 37
}curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/items"Ausprobieren
GET /api/v1/items/{id}
One item
The item as it is now (as /items shows it), also once it is no longer listed.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
idpath, Pflicht | integer | The item's id.Beispiel: 77 |
Antworten
- 200 The item.
application/jsonItem - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 404 Not found among the items you can see.
application/jsonError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
{
"attributes": {
"availability": "in stock",
"shipping": 0
},
"brand": "Lenovo",
"category": {
"name": "Laptops",
"path": "Computers > Laptops",
"slug": "computers-laptops",
"source": "AI"
},
"currency": "EUR",
"datasets": [
"Laptops DACH"
],
"firstSeenAt": "2026-09-01T10:00:00Z",
"gtin": "0196802123456",
"id": 77,
"image": "https://www.notebookshop.example/img/thinkpad-x1.jpg",
"lastChangedAt": "2026-10-06T21:03:00Z",
"lastSeenAt": "2026-10-07T09:12:00Z",
"mpn": "21KC004MGE",
"previousPrice": 1499,
"price": 1399,
"priceChangedAt": "2026-10-06T21:03:00Z",
"removedAt": "2026-10-07T03:30:00Z",
"site": {
"attribution": "Source: European Commission, Weekly Oil Bulletin, CC BY 4.0",
"host": "www.notebookshop.example",
"id": 4,
"name": "Notebookshop"
},
"source": {
"modelId": 31,
"name": "Notebookshop – Laptops"
},
"title": "Lenovo ThinkPad X1 Carbon Gen 12",
"url": "https://www.notebookshop.example/p/thinkpad-x1"
}curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/items/77"Ausprobieren
GET /api/v1/items/{id}/history
An item's history
Every change of the item within your plan's history, oldest first: its prices over time.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
idpath, Pflicht | integer | The item's id.Beispiel: 77 |
Antworten
- 200 The item's history.
application/jsonHistoryEntry[] - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 404 Not found among the items you can see.
application/jsonError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
[
{
"changes": {
"availability": [
"2-3 days",
"in stock"
]
},
"id": 812,
"kind": "NEW",
"observedAt": "2026-10-06T21:03:00Z",
"previousPrice": 1499,
"price": 1399
}
]curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/items/77/history"Ausprobieren
Changes
Every new item, change and removal, in order: to keep a copy in sync.
GET /api/v1/changes
The change feed
Everything that happened after after, oldest first. Start with after=0, then pass each answer's nextCursor as after; repeat while hasMore is true. Store the last cursor and go on from it next time: you get each change exactly once. Changes show here about 30 seconds after they happen. Paid plans (on Free it answers 402).
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
datasetquery | integer | One of your datasets (its id from /datasets); without it, all of them.Beispiel: 12 |
afterquery | integer | The cursor: the nextCursor of the last answer (0 = from the beginning of your plan's history).Beispiel: 0Standard: 0 |
limitquery | integer | Changes per answer, 1 to 1000. Beispiel: 1000Standard: 500 |
Antworten
- 200 The next changes.
application/jsonChangePage - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
{
"changes": [
{
"changes": {
"price": [
1499,
1399
]
},
"id": 812,
"item": {
"currency": null,
"id": null,
"site": null,
"title": null,
"url": null
},
"kind": "NEW",
"observedAt": "2026-10-06T21:03:00Z",
"previousPrice": 1499,
"price": 1399
}
],
"hasMore": true,
"nextCursor": 1811
}curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/changes"Ausprobieren
GET /api/v1/changes/recent
Recent changes, newest first
For people: the latest changes, newest first, optionally only of one kind. Page back with before. To sync a copy, use /changes. A change shows here when it shows in /changes (within about 30 seconds), so the id of the newest one is a safe place to start /changes?after= from.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
datasetquery | integer | One of your datasets (its id from /datasets); without it, all of them.Beispiel: 12 |
kindquery | string, einer von NEW, CHANGED, REMOVED, RELISTED, PRICE_DROP, PRICE_RISE | NEW, CHANGED, REMOVED, RELISTED, PRICE_DROP or PRICE_RISE. |
beforequery | integer | The last id of the previous page.Beispiel: 1811 |
limitquery | integer | Changes per answer, 1 to 200. Beispiel: 50Standard: 50 |
Antworten
- 200 The changes.
application/jsonChangePage - 400 A parameter is not valid;
messagesays which.application/jsonError - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
{
"changes": [
{
"changes": {
"price": [
1499,
1399
]
},
"id": 812,
"item": {
"currency": null,
"id": null,
"site": null,
"title": null,
"url": null
},
"kind": "NEW",
"observedAt": "2026-10-06T21:03:00Z",
"previousPrice": 1499,
"price": 1399
}
],
"hasMore": true,
"nextCursor": 1811
}curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/changes/recent"Ausprobieren
Products
The same product across shops: compare its prices.
GET /api/v1/products
Find products across shops
Products with offers in your datasets: the same product in several shops, matched by GTIN, else by brand and part number, with its price range and how many shops sell it.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
datasetquery | integer | One of your datasets (its id from /datasets); without it, all of them.Beispiel: 12 |
qquery | string | Words to look for (all of them, in any order) in the title, brand, codes and other values of the item; parts of words count. Beispiel: thinkpad |
categoryquery | string | A category's slug (from /facets), with its subcategories.Beispiel: computers-laptops |
brandquery | string | The brand, as the shops name it. Beispiel: Lenovo |
gtinquery | string | EAN/UPC/ISBN-13: the same product in every shop (leading zeros may be left out). Beispiel: 0196802123456 |
currencyquery | string | ISO 4217 code. Beispiel: EUR |
minShopsquery | integer | Sold by at least this many websites (2: products to compare). Beispiel: 2Standard: 1 |
sortquery | string, einer von -offers, -shops, price, -price | -offers (the default), -shops, price (lowest first) or -price. |
pagequery | integer | The page, from 0. Beispiel: 0Standard: 0 |
sizequery | integer | Products per page, 1 to 200. Beispiel: 50Standard: 50 |
Antworten
- 200 A page of products.
application/jsonPageDtoProduct - 400 A parameter is not valid;
messagesays which.application/jsonError - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
{
"content": [
{
"brand": "Lenovo",
"category": {
"name": null,
"path": null,
"slug": null,
"source": null
},
"gtin": "0196802123456",
"id": "0196802123456",
"mpn": "21KC004MGE",
"offers": 6,
"prices": [
null
],
"shops": 5,
"title": "Lenovo ThinkPad X1 Carbon Gen 12"
}
],
"page": 0,
"size": 50,
"totalElements": 1804,
"totalPages": 37
}curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/products"Ausprobieren
GET /api/v1/products/{id}
One product with its offers
A product by its id (a GTIN, or a brand-MPN key) with all its offers you can see, cheapest first.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
idpath, Pflicht | string | The product's id: a GTIN (any of its forms) or a brand-MPN key.Beispiel: 0196802123456 |
datasetquery | integer | One of your datasets (its id from /datasets); without it, all of them.Beispiel: 12 |
currencyquery | string | Only offers in this currency (ISO 4217). Beispiel: EUR |
Antworten
- 200 The product and its offers.
application/jsonProductDetail - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 404 No offers of this product among the items you can see.
application/jsonError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
{
"offers": [
{
"attributes": {
"availability": "in stock",
"shipping": 0
},
"brand": "Lenovo",
"category": {
"name": null,
"path": null,
"slug": null,
"source": null
},
"currency": "EUR",
"datasets": [
"Laptops DACH"
],
"firstSeenAt": "2026-09-01T10:00:00Z",
"gtin": "0196802123456",
"id": 77,
"image": "https://www.notebookshop.example/img/thinkpad-x1.jpg",
"lastChangedAt": "2026-10-06T21:03:00Z",
"lastSeenAt": "2026-10-07T09:12:00Z",
"mpn": "21KC004MGE",
"previousPrice": 1499,
"price": 1399,
"priceChangedAt": "2026-10-06T21:03:00Z",
"removedAt": "2026-10-07T03:30:00Z",
"site": {
"attribution": null,
"host": null,
"id": null,
"name": null
},
"source": {
"modelId": null,
"name": null
},
"title": "Lenovo ThinkPad X1 Carbon Gen 12",
"url": "https://www.notebookshop.example/p/thinkpad-x1"
}
],
"product": {
"brand": "Lenovo",
"category": {
"name": "Laptops",
"path": "Computers > Laptops",
"slug": "computers-laptops",
"source": "AI"
},
"gtin": "0196802123456",
"id": "0196802123456",
"mpn": "21KC004MGE",
"offers": 6,
"prices": [
{
"currency": null,
"max": null,
"min": null,
"offers": null
}
],
"shops": 5,
"title": "Lenovo ThinkPad X1 Carbon Gen 12"
}
}curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/products/0196802123456"Ausprobieren
Export
Everything at once, as CSV or NDJSON.
GET /api/v1/export
Export items
All matching items, streamed as CSV (UTF-8, a header row) or NDJSON (one JSON object per line), with the filters of /items. Rows count against your plan's export rows per month. On paid plans, rows beyond them are billed as overage per started 10,000 and the export is complete (X-Export-Overage); on Free, in the trial, or with overage switched off, an export that would go beyond them ends at the limit and says so in X-Export-Truncated.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
formatquery | string, einer von csv, ndjson | csv (the default) or ndjson. |
datasetquery | integer | One of your datasets (its id from /datasets); without it, all of them.Beispiel: 12 |
sitequery | integer | Only items of this website (id from /facets).Beispiel: 4 |
categoryquery | string | A category's slug (from /facets), with its subcategories.Beispiel: computers-laptops |
qquery | string | Words to look for (all of them, in any order) in the title, brand, codes and other values of the item; parts of words count. Beispiel: thinkpad |
minPricequery | number | Lowest price, in the item's currency. Beispiel: 500 |
maxPricequery | number | Highest price, in the item's currency. Beispiel: 1500 |
currencyquery | string | ISO 4217 code. Beispiel: EUR |
statusquery | string, einer von active, removed, all | active (listed now, the default), removed (no longer listed) or all. |
changedSincequery | string (date-time) | Only items with a change after this time (ISO 8601), e.g. the start of your last sync. Beispiel: 2026-10-01T00:00:00Z |
gtinquery | string | EAN/UPC/ISBN-13: the same product in every shop (leading zeros may be left out). Beispiel: 0196802123456 |
Antworten
- 200 The rows, streamed.
application/x-ndjsonstringtext/csvstringX-Export-Matching: WithX-Export-Truncated: how many rows matched.X-Export-Overage:trueif rows beyond the month's quota are in it, billed as overage.X-Export-Rows: Rows in this export.X-Export-Rows-Remaining: Export rows left this month after it.X-Export-Truncated:trueif the export ended at the monthly limit.
- 400 A parameter is not valid;
messagesays which.application/jsonError - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/export"Ausprobieren
Nur der Anfang der Antwort wird gelesen und gezeigt, und der Export endet dort; die Zeilen bis dahin zählen zu Ihren Exportzeilen im Monat. Filter halten ihn klein.
Plan
Your plan, its limits and this month's use.
GET /api/v1/plan
Your plan and this month's use
The plan in effect, its limits (null is unlimited), the calls and export rows used this month and when they start over. Every answer also carries RateLimit-* and X-Quota-* headers.
Antworten
- 200 Your plan.
application/jsonPlanInfo - 401 No API key, or one that is invalid or revoked.
application/jsonError - 402 Not in your plan (a dataset beyond it, the change feed on Free), or a payment overdue for 30 days (
limit: paymentOverdue).application/jsonLimitError - 429 Too many requests per second, or the month's calls are used up (
limitsays which).Retry-Aftersays when to try again.application/jsonLimitError
Beispiel
{
"limits": {
"datasets": 10,
"apiCallsPerMonth": 250000,
"ratePerSecond": 20,
"delayHours": 0,
"historyDays": 365,
"exportRowsPerMonth": 1000000,
"changeFeed": true,
"webhooks": true
},
"lockedDatasets": 0,
"name": "Pro",
"plan": "pro",
"status": "ACTIVE",
"trialEndsAt": "2026-10-21T09:00:00Z",
"upgradeUrl": "https://pricana.io/pricing",
"usage": {
"apiCalls": 48211,
"exportRows": 12000,
"resetsAt": "2026-11-01T00:00:00Z"
}
}curl -H "Authorization: Bearer $PRICANA_KEY" \
"https://pricana.io/api/v1/plan"Ausprobieren
Webhooks
Diese schickt Pricana an Ihren Endpunkt. Endpunkte richten Sie im Portal ein (API); der Leitfaden erklärt die Signatur. Leitfaden Webhooks
POST https://your-server.example/…
New changes of the change feed (sent by Pricana)
Pricana posts the next changes of your datasets to your endpoint, in order, up to 100 at a time, as the change feed lists them (type: changes), and a test when you send one from the portal (type: ping). Check the signature before you use the body: HMAC-SHA256 with your endpoint's secret over <t>.<body>, compared with each v1 value. Answer with any 2xx within 10 seconds; anything else is tried again after 1, 5, 15 and 30 minutes, then 1, 2 and every 4 hours, and later changes wait. After 24 hours of failures the endpoint is turned off and your team gets an email.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
Pricana-Signatureheader, Pflicht | string | t=<unix seconds>,v1=<hex HMAC-SHA256>; a second v1 while a rolled secret's old one is still valid.Beispiel: t=1791374400,v1=26ff918ca24488a1a2aa21935c219eaed5c31c721399ca4d400ebecf2784fdf4 |
Pricana-Event-Idheader, Pflicht | string | The event's id, as id in the body.Beispiel: evt_5f1c0b2a9d7e4c3b8a6f0e1d |
Pricana-Event-Typeheader, Pflicht | string | changes or ping.Beispiel: changes |
Pricana-Delivery-Attemptheader, Pflicht | integer | 1 for the first attempt, then 2, 3 … Beispiel: 1 |
Body, den Pricana schickt: WebhookEvent
{
"changes": [
{
"changes": {
"price": [
1499,
1399
]
},
"id": 812,
"item": {
"currency": null,
"id": null,
"site": null,
"title": null,
"url": null
},
"kind": "NEW",
"observedAt": "2026-10-06T21:03:00Z",
"previousPrice": 1499,
"price": 1399
}
],
"createdAt": "2026-10-07T09:12:31Z",
"cursor": 1811,
"id": "evt_5f1c0b2a9d7e4c3b8a6f0e1d",
"type": "changes"
}Antworten
- 200 Received (any 2xx will do; the body is ignored).
- default Anything else (and no answer in 10 seconds): tried again later.
Datenmodell
CategoryRef
The item's category in Pricana's taxonomy.
| Name | Typ | Beschreibung |
|---|---|---|
name | string | Beispiel: "Laptops" |
path | string | Beispiel: "Computers > Laptops" |
slug | string | Beispiel: "computers-laptops" |
source | string, einer von AI, MANUAL | Who chose it (EU AI Act transparency): AI, or MANUAL (a person). Beispiel: "AI" |
Change
One entry of the change feed: an item appeared (NEW), changed (CHANGED), was no longer listed (REMOVED) or came back (RELISTED). id is the cursor.
| Name | Typ | Beschreibung |
|---|---|---|
changes | object | Values that changed, by name: [old, new]. Beispiel: {"price":[1499,1399]} |
id | integer | Increasing: pass the last one you have as after.Beispiel: 812 |
item | ChangeItem | Null if the item is gone from your data meanwhile. |
kind | string, einer von NEW, CHANGED, REMOVED, RELISTED | |
observedAt | string (date-time) | Beispiel: "2026-10-06T21:03:00Z" |
previousPrice | number | null | Set when the price changed. Beispiel: 1499 |
price | number | null | Beispiel: 1399 |
ChangeItem
The item a change belongs to (its title and link then).
| Name | Typ | Beschreibung |
|---|---|---|
currency | string | null | Beispiel: "EUR" |
id | integer | Beispiel: 77 |
site | SiteRef | |
title | string | Beispiel: "Lenovo ThinkPad X1 Carbon Gen 12" |
url | string | null | Beispiel: "https://www.notebookshop.example/p/thinkpad-x1" |
ChangePage
A page of changes. Pass nextCursor on to get the next entries: as after to /changes, as before to /changes/recent.
| Name | Typ | Beschreibung |
|---|---|---|
changes | Change[] | |
hasMore | boolean | More changes are waiting now: ask again at once. Beispiel: true |
nextCursor | integer | Store it, and continue from it next time (after for /changes, before for /changes/recent).Beispiel: 1811 |
Dataset
A dataset: the listings of a set of websites on one topic, as your plan shows them.
| Name | Typ | Beschreibung |
|---|---|---|
description | string | null | Beispiel: "Laptops and notebooks from shops in Germany, Austria and Switzerland." |
healthyModels | integer | Sources collecting without problems; the others are being repaired. Beispiel: 14 |
id | integer | Use it as dataset in other requests.Beispiel: 12 |
items | integer | Items listed now. Beispiel: 18342 |
models | integer | Sources: one listing of one website each. Beispiel: 14 |
name | string | Beispiel: "Laptops DACH" |
newestScrapeAt | string (date-time) | null | When a source of the dataset was last read; null before the first. Beispiel: "2026-10-07T09:12:00Z" |
oldestScrapeAt | string (date-time) | null | When the source read longest ago was read. Beispiel: "2026-10-07T05:40:00Z" |
sites | integer | Websites the items come from. Beispiel: 9 |
Error
Every error answer.
| Name | Typ | Beschreibung |
|---|---|---|
docsUrl | string | The docs' page about this error. Beispiel: "https://pricana.io/docs/errors#not-found" |
error | string | Beispiel: "Not Found" |
message | string | Beispiel: "Item 77 not found" |
status | integer | Beispiel: 404 |
FacetCategory
A category among the facets, with its items (subcategories included).
| Name | Typ | Beschreibung |
|---|---|---|
id | integer | Beispiel: 8 |
items | integer | Beispiel: 1804 |
name | string | Beispiel: "Laptops" |
parentId | integer | null | Null for a top category. Beispiel: 2 |
path | string | Beispiel: "Computers > Laptops" |
slug | string | Beispiel: "computers-laptops" |
FacetCurrency
A currency among the facets, with its items.
| Name | Typ | Beschreibung |
|---|---|---|
code | string | Beispiel: "EUR" |
items | integer | Beispiel: 17920 |
Facets
What the items can be filtered by, with counts.
| Name | Typ | Beschreibung |
|---|---|---|
categories | FacetCategory[] | |
currencies | FacetCurrency[] | |
sites | FacetSite[] |
FacetSite
A website among the facets, with its items.
| Name | Typ | Beschreibung |
|---|---|---|
host | string | Beispiel: "www.notebookshop.example" |
id | integer | Beispiel: 4 |
items | integer | Beispiel: 2310 |
name | string | Beispiel: "Notebookshop" |
HistoryEntry
One step in an item's history.
| Name | Typ | Beschreibung |
|---|---|---|
changes | object | Values that changed, by name: [old, new]. Beispiel: {"availability":["2-3 days","in stock"]} |
id | integer | Beispiel: 812 |
kind | string, einer von NEW, CHANGED, REMOVED, RELISTED | |
observedAt | string (date-time) | Beispiel: "2026-10-06T21:03:00Z" |
previousPrice | number | null | Set when the price changed. Beispiel: 1499 |
price | number | null | Beispiel: 1399 |
Item
A listing (an offer of a product in a shop), as it is now: the shop's own values, with Pricana's category and the product codes that identify it across shops.
| Name | Typ | Beschreibung |
|---|---|---|
attributes | object | Further values the shop shows (stock, shipping, ratings …), by name. Beispiel: {"availability":"in stock","shipping":0} |
brand | string | null | Beispiel: "Lenovo" |
category | CategoryRef | Null while it has none. |
currency | string | null | Beispiel: "EUR" |
datasets | string[] | Your datasets the item is in. Beispiel: ["Laptops DACH"] |
firstSeenAt | string (date-time) | Beispiel: "2026-09-01T10:00:00Z" |
gtin | string | null | EAN/UPC/ISBN-13 (8, 13 or 14 digits): the same product in every shop. Null when the shop doesn't name it. Beispiel: "0196802123456" |
id | integer | Beispiel: 77 |
image | string | null | The shop's product image, if it shows one. Beispiel: "https://www.notebookshop.example/img/thinkpad-x1.jpg" |
lastChangedAt | string (date-time) | The last time a value changed (use it with changedSince).Beispiel: "2026-10-06T21:03:00Z" |
lastSeenAt | string (date-time) | The last time a scrape found it. Beispiel: "2026-10-07T09:12:00Z" |
mpn | string | null | The manufacturer's part number. Beispiel: "21KC004MGE" |
previousPrice | number | null | The price before the last price change; null if it never changed. Beispiel: 1499 |
price | number | null | Null when the shop shows none. Beispiel: 1399 |
priceChangedAt | string (date-time) | null | When the price last changed. Beispiel: "2026-10-06T21:03:00Z" |
removedAt | string (date-time) | null | When the shop stopped listing it; null while it is listed. Beispiel: "2026-10-07T03:30:00Z" |
site | SiteRef | |
source | Source | |
title | string | null | Beispiel: "Lenovo ThinkPad X1 Carbon Gen 12" |
url | string | null | The item's page in the shop. Beispiel: "https://www.notebookshop.example/p/thinkpad-x1" |
LimitError
A plan limit (402) or a rate or monthly limit (429): which one, its value in your plan, and where to upgrade.
| Name | Typ | Beschreibung |
|---|---|---|
allowed | object | Its value in your plan. Beispiel: 100000 |
docsUrl | string | Beispiel: "https://pricana.io/docs/errors#apiCallsPerMonth" |
error | string | Beispiel: "Too Many Requests" |
limit | string | The limit: datasets, changeFeed, apiCallsPerMonth, ratePerSecond, exportRowsPerMonth or paymentOverdue. Beispiel: "apiCallsPerMonth" |
message | string | Beispiel: "The monthly quota of 100,000 calls is used up; it starts over on 1 November" |
plan | string | Beispiel: "pro" |
status | integer | Beispiel: 429 |
upgradeUrl | string | Beispiel: "https://pricana.io/pricing" |
PageDtoItem
A page of results.
| Name | Typ | Beschreibung |
|---|---|---|
content | Item[] | |
page | integer | This page, from 0. Beispiel: 0 |
size | integer | Results per page. Beispiel: 50 |
totalElements | integer | All results. Beispiel: 1804 |
totalPages | integer | Pages in all. Beispiel: 37 |
PageDtoProduct
A page of results.
| Name | Typ | Beschreibung |
|---|---|---|
content | Product[] | |
page | integer | This page, from 0. Beispiel: 0 |
size | integer | Results per page. Beispiel: 50 |
totalElements | integer | All results. Beispiel: 1804 |
totalPages | integer | Pages in all. Beispiel: 37 |
PlanInfo
Your plan in effect (Free once a trial ended), its limits and this month's use.
| Name | Typ | Beschreibung |
|---|---|---|
limits | object | The limits by name; null is unlimited. Beispiel: {"datasets":10,"apiCallsPerMonth":250000,"ratePerSecond":20,"delayHours":0,"historyDays":365,"exportRowsPerMonth":1000000,"changeFeed":true,"webhooks":true} |
lockedDatasets | integer | Your datasets beyond what the plan includes: they answer 402. Beispiel: 0 |
name | string | Beispiel: "Pro" |
plan | string | Beispiel: "pro" |
status | string | null | TRIALING, ACTIVE, PAST_DUE or CANCELED; null without a subscription. Beispiel: "ACTIVE" |
trialEndsAt | string (date-time) | null | When the trial ends (status TRIALING). Beispiel: "2026-10-21T09:00:00Z" |
upgradeUrl | string | Where to get more: the plans and their prices. Beispiel: "https://pricana.io/pricing" |
usage | PlanUsage | This month's use; null for an operator's token. |
PlanUsage
Calls with API keys or tokens and exported rows this calendar month (UTC).
| Name | Typ | Beschreibung |
|---|---|---|
apiCalls | integer | Beispiel: 48211 |
exportRows | integer | Beispiel: 12000 |
resetsAt | string (date-time) | When both start over (the first of next month, 00:00 UTC). Beispiel: "2026-11-01T00:00:00Z" |
PriceRange
The lowest and highest price of a product's offers in one currency.
| Name | Typ | Beschreibung |
|---|---|---|
currency | string | Beispiel: "EUR" |
max | number | Beispiel: 1529 |
min | number | Beispiel: 1349 |
offers | integer | Beispiel: 6 |
Product
A product across shops: the offers of the same product, matched by GTIN, else by brand and part number.
| Name | Typ | Beschreibung |
|---|---|---|
brand | string | null | Beispiel: "Lenovo" |
category | CategoryRef | Null while it has none. |
gtin | string | null | Beispiel: "0196802123456" |
id | string | Its GTIN (digits), else its brand-MPN key. Beispiel: "0196802123456" |
mpn | string | null | Beispiel: "21KC004MGE" |
offers | integer | Offers (items) of it you can see. Beispiel: 6 |
prices | PriceRange[] | The price range per currency. |
shops | integer | Different websites selling it. Beispiel: 5 |
title | string | null | Beispiel: "Lenovo ThinkPad X1 Carbon Gen 12" |
ProductDetail
A product with all its offers, cheapest first.
SiteRef
The website an item comes from.
| Name | Typ | Beschreibung |
|---|---|---|
attribution | string | null | The source's licence and credit (open data, e.g. CC BY 4.0): pass it on with its data. Null for other sources. Beispiel: "Source: European Commission, Weekly Oil Bulletin, CC BY 4.0" |
host | string | Beispiel: "www.notebookshop.example" |
id | integer | Beispiel: 4 |
name | string | Beispiel: "Notebookshop" |
Source
The source (one listing of one website) an item was read from.
| Name | Typ | Beschreibung |
|---|---|---|
modelId | integer | Beispiel: 31 |
name | string | Beispiel: "Notebookshop – Laptops" |
WebhookEvent
What your webhook endpoint receives: the next changes of the change feed, in order, up to 100 at a time (type changes), or a test from the portal (type ping, no changes).
| Name | Typ | Beschreibung |
|---|---|---|
changes | Change[] | |
createdAt | string (date-time) | Beispiel: "2026-10-07T09:12:31Z" |
cursor | integer | null | The id of the last change in it (null for a ping): /changes?after= goes on from it.Beispiel: 1811 |
id | string | The same on every attempt and when sent again: drop repeats by it. Beispiel: "evt_5f1c0b2a9d7e4c3b8a6f0e1d" |
type | string, einer von changes, ping | Beispiel: "changes" |