PIM · API
Producten
GET /products: wanneer een product verschijnt, de filters, het antwoord en de velden.
Producten ophalen
/products
De producten die je mag verkopen, met de aanbiedingen van de leveranciers.
Dit adres geeft de producten die voor jouw bedrijf beschikbaar zijn, met per product de gegevens, de status en de aanbiedingen van leveranciers. Het antwoord is een pagina met producten. Hoe je alle pagina's doorloopt, staat bij Synchroniseren.
# Zet je token in een omgevingsvariabele. Zet het nooit in een script dat je deelt.
export PIM_API_TOKEN='<jouw-token>'
# -g laat curl de blokhaken in filter[...] ongemoeid.
curl -sS -g "https://pim.internetservicebureau.nl/api/v1/products?per_page=2" \
-H "Accept: application/json" \
-H "Authorization: Bearer $PIM_API_TOKEN"
// Alleen in code op je eigen server: zet het token nooit in browsercode.
// Top-level await werkt in een ES-module (een .mjs-bestand of "type": "module").
const token = process.env.PIM_API_TOKEN;
const response = await fetch('https://pim.internetservicebureau.nl/api/v1/products?per_page=2', {
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`,
},
});
// Een fout is ook JSON: {"message": "..."}
console.log(response.status, await response.json());
<?php
// Het token komt uit de omgeving, niet uit de code.
$token = getenv('PIM_API_TOKEN');
$curl = curl_init('https://pim.internetservicebureau.nl/api/v1/products?per_page=2');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
"Authorization: Bearer {$token}",
],
]);
$body = json_decode(curl_exec($curl), true);
// Een fout is ook JSON: {"message": "..."}
echo curl_getinfo($curl, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($body);
import json
import os
import urllib.error
import urllib.request
# Het token komt uit de omgeving, niet uit de code.
token = os.environ["PIM_API_TOKEN"]
request = urllib.request.Request(
"https://pim.internetservicebureau.nl/api/v1/products?per_page=2",
headers={
"Accept": "application/json",
"Authorization": f"Bearer {token}",
},
)
try:
with urllib.request.urlopen(request) as response:
print(response.status, json.load(response))
except urllib.error.HTTPError as error:
# Een fout is ook JSON: {"message": "..."}
print(error.code, json.load(error))
Wanneer een product verschijnt
Een product staat in de lijst als dit allemaal klopt:
- Het product heeft een EAN.
- Je hebt een actief klantartikel voor dit product. Een verwijderd of op inactief gezet artikel telt niet. Is het artikel in je eigen kassa of ERP op inactief gezet, dan blijft het ook weg.
- Er is minstens één actief aanbod dat je mag gebruiken. Of dat aanbod voor jou geldt, hangt af van je abonnement, licenties en merkrechten, zie Hoe het werkt.
Er is één uitzondering. Heeft een artikel uit je eigen kassa of ERP een eigen voorraad groter dan nul, dan blijft het in de lijst staan, ook als het aanbod van de leverancier uitloopt of niet verkrijgbaar is. Dat aanbod moet je dan nog wel mogen gebruiken.
Valt een product uit de lijst, dan krijg je daar geen bericht van. Het is er gewoon niet meer. Meer daarover bij Synchroniseren.
Parameters
| Naam | Type | Verplicht | Omschrijving |
|---|---|---|---|
page |
integer | Optioneel | Het paginanummer, te beginnen bij 1. Volg liever links.next. |
per_page |
integer | Optioneel | Het aantal producten per pagina. Standaard 100, maximaal 1000. Geef je 0 of minder, of meer dan 1000, dan krijg je geen foutmelding maar 100 producten. |
limit |
integer | Optioneel | Hetzelfde als per_page. Geef je allebei op, dan wint per_page. |
filter[updated_at] |
string | Optioneel | Alleen producten die zijn gewijzigd op of na (of voor) een tijdstip. Zie hieronder. |
filter[stock] |
string | Optioneel | Filter op je eigen voorraad uit je kassa of ERP. Zie hieronder. |
filter[nut_plas_number] |
string | Optioneel | Een of meer NUT- of PLAS-nummers, gescheiden door een komma. Zoekt in de aanbiedingen die je mag gebruiken. |
filter[ean13] |
string | Optioneel | Eén EAN. Zoekt op de EAN van het product en op de EAN van de aanbiedingen. |
filter[eancode] |
string | Optioneel | Hetzelfde als filter[ean13]. |
Het antwoord zegt niet hoeveel producten er in totaal zijn. Je weet dat je op de laatste pagina bent als links.next null is.
Filters
Gewijzigd sinds (updated_at)
Met dit filter vraag je alleen de producten op die zijn gewijzigd. Zet er een voorvoegsel voor, zoals >=, en daarachter een tijdstip.
| Voorvoegsel | In de URL | Betekenis |
|---|---|---|
>= |
%3E%3D |
Groter dan of gelijk aan. Dit gebruik je om wijzigingen op te halen. |
> |
%3E |
Groter dan. |
<= |
%3C%3D |
Kleiner dan of gelijk aan. |
< |
%3C |
Kleiner dan. |
<> |
%3C%3E |
Ongelijk aan. |
= |
%3D |
Gelijk aan. Dit is ook wat je krijgt zonder voorvoegsel. |
De tekens >, < en = kunnen niet zomaar in een URL. Schrijf ze als %3E, %3C en %3D. Dus >= wordt %3E%3D. Functies als http_build_query, URLSearchParams en de params van requests doen dat voor je. Bij curl met -g schrijf je het zelf.
Het tijdstip mag in een van deze vormen:
2026-03-12T10:00:002026-03-12 10:00:00, met de spatie als%20in de URL2026-03-12, dat telt als middernacht aan het begin van die dag
Geef de tijd in Nederlandse tijd
De PIM rekent met Nederlandse tijd (Europe/Amsterdam). Een tijdzone achter het tijdstip, zoals Z of +01:00, wordt niet omgerekend. De kloktijd telt. Geef dus de tijd zoals die in Nederland op de klok staat. De tijdstippen in het antwoord (changed_at) hebben de Nederlandse tijdzone al.
Wat telt als wijziging? Een product komt mee als er iets veranderde in zijn inhoud: de naam, beschrijving, afbeeldingen, prijs of voorraad. Dat kan gaan om het product zelf, om een aanbod dat je mag gebruiken, of om je eigen klantartikel. Bij een artikel uit je eigen kassa of ERP tellen ook een wijziging van je eigen voorraad en een wijziging van de status van het aanbod mee.
Alle producten die sinds 12 maart 2026 om 10:00 uur zijn gewijzigd:
curl -sS -g "https://pim.internetservicebureau.nl/api/v1/products?filter[updated_at]=%3E%3D2026-03-12T10:00:00" \
-H "Accept: application/json" \
-H "Authorization: Bearer $PIM_API_TOKEN"
Zonder voorvoegsel zoekt de PIM op precies dat tijdstip. Dat levert bijna altijd een lege lijst op. Gebruik daarom een voorvoegsel.
Eigen voorraad (stock)
Dit filter werkt op stock bovenaan het product: je eigen voorraad uit je kassa of ERP. Het gebruikt dezelfde voorvoegsels als hierboven. De voorraad van leveranciers telt niet mee. Producten zonder eigen voorraad komen er niet door, ook niet bij <=5.
De waarde moet een getal zijn, eventueel met een voorvoegsel. Anders krijg je 422, zie Foutmeldingen.
curl -sS -g "https://pim.internetservicebureau.nl/api/v1/products?filter[stock]=%3E%3D5" \
-H "Accept: application/json" \
-H "Authorization: Bearer $PIM_API_TOKEN"
Eén product opzoeken (ean13)
curl -sS -g "https://pim.internetservicebureau.nl/api/v1/products?filter[ean13]=8710000000001" \
-H "Accept: application/json" \
-H "Authorization: Bearer $PIM_API_TOKEN"
Een onbekend filter geeft een 400. Je kunt filters combineren: ze gelden dan allemaal tegelijk.
Het antwoord
Het antwoord is JSON met data, links en meta. Er is geen totaal. links.last is altijd null. Hieronder één product. De waarden zijn verzonnen.
{
"data": [
{
"ean13": "8710000000001",
"reference": "REF-1",
"name": "Voorbeeldmerk Voorbeeld Vitamine C - 90cp",
"original_name": "Voorbeeld Vitamine C",
"nut_plas_number": null,
"brand": "Voorbeeldmerk",
"vat": 9,
"category": null,
"content": "90cp",
"unit_value": 90,
"unit_type": "cp",
"short_description": null,
"description": "<p>Voorbeeldomschrijving.</p>",
"ingredients": [],
"specifications": [],
"attributes": [],
"nutrition": [],
"images": [
"https://pim.internetservicebureau.nl/storage/img/voorbeeld.jpg"
],
"status": "active",
"eol_date": null,
"field_sources": {
"name": "Voorbeeldleverancier",
"brand": "Voorbeeldleverancier",
"content": "Voorbeeldleverancier",
"short_description": "Voorbeeldleverancier",
"description": "Voorbeeldleverancier",
"images": "Voorbeeldleverancier"
},
"changed_at": {
"name": "2026-03-01T09:00:00+01:00",
"short_description": null,
"description": null,
"images": null,
"price": "2026-03-12T11:30:00+01:00",
"stock": "2026-03-12T11:30:00+01:00"
},
"stock": 7,
"suppliers": [
{
"licence": "",
"supplier": "Voorbeeldleverancier",
"sku": "V-1",
"name": "Voorbeeld Vitamine C",
"nut_plas_number": null,
"status": "active",
"stock": 40,
"price": 8.5,
"price_incl": "9.27",
"advice_price": 14.95,
"wholesale_price": null,
"category": null,
"ingredients": [],
"attributes": [],
"nutrition": [],
"description": null,
"clean_description": null,
"images": [
"https://pim.internetservicebureau.nl/storage/img/voorbeeld.jpg"
]
}
]
}
],
"links": {
"first": "https://pim.internetservicebureau.nl/api/v1/products?page=1",
"last": null,
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"current_page_url": "https://pim.internetservicebureau.nl/api/v1/products?page=1",
"from": 1,
"path": "https://pim.internetservicebureau.nl/api/v1/products",
"per_page": 100,
"to": 1
}
}
Velden van een product
| Veld | Type | Omschrijving |
|---|---|---|
ean13 |
string | De EAN van het product. Hieraan herken je een product. Producten zonder EAN komen niet in de lijst. |
reference |
string|null | Referentie van het product. |
name |
string|null | De volledige naam: merk, naam en inhoud achter elkaar, zoals Voorbeeldmerk Voorbeeld Vitamine C - 90cp. |
original_name |
string|null | De naam van het centrale product, zonder merk en inhoud erbij. |
nut_plas_number |
string|null | Het NUT- of PLAS-nummer, uit het hoofdaanbod of anders uit een ander aanbod dat je mag gebruiken. |
brand |
string|null | De merknaam in een vaste schrijfwijze. |
vat |
integer | Het btw-percentage. Is er niets vastgelegd, dan is het 21. |
category |
string|null | De categorie van het hoofdaanbod. |
content |
string|null | De inhoud als tekst, bijvoorbeeld 90cp. Zonder bekende inhoud is het 1st. |
unit_value |
integer|number|null | Het getal uit de inhoud, bijvoorbeeld 90. |
unit_type |
string|null | De eenheid uit de inhoud, bijvoorbeeld cp of st. |
short_description |
string|null | Korte beschrijving. Kan HTML bevatten. |
description |
string|null | Beschrijving. Kan HTML bevatten. |
ingredients |
array | Ingrediënten. Leeg als er geen zijn: []. |
specifications |
array | Specificaties. Leeg als er geen zijn: []. |
attributes |
array | Kenmerken van het hoofdaanbod. Leeg als er geen zijn: []. |
nutrition |
array | Voedingswaarden. Leeg als er geen zijn: []. |
images |
array | Afbeeldingen. Meestal een lijst met volledige internetadressen. Een afbeelding kan ook een object zijn met url en een markering voor de hoofdafbeelding. |
status |
string | De status van het product: active, eol of unavailable. |
eol_date |
string|null | De einddatum (ISO 8601) van een product dat door je eigen voorraad in de lijst blijft, als de leverancier die kent. Anders null. |
field_sources |
object | Per veld waar de inhoud vandaan komt: de naam van een leverancier of Manual. Velden: name, brand, content, short_description, description, images. |
changed_at |
object | Per veld het tijdstip van de laatste wijziging (ISO 8601) of null. Velden: name, short_description, description, images, price, stock. |
stock |
integer|null | Je eigen voorraad uit je kassa of ERP. null voor artikelen die daar niet vandaan komen. |
suppliers |
array | De aanbiedingen van leveranciers die je mag gebruiken. Zie hieronder. |
Velden van een aanbod in suppliers
| Veld | Type | Omschrijving |
|---|---|---|
licence |
string | De licentie die voor dit product nodig is. Een lege tekst als er geen nodig is. |
supplier |
string|null | De naam van de leverancier. |
sku |
string|null | Het artikelnummer van de leverancier. |
name |
string|null | De naam zoals de leverancier die geeft. |
nut_plas_number |
string|null | Het NUT- of PLAS-nummer van dit aanbod. |
status |
string | De status van het aanbod. Hier staan alleen actieve aanbiedingen, dus active. |
stock |
integer | De voorraad bij de leverancier. |
price |
number | De prijs van de leverancier, zonder btw. |
price_incl |
string | Dezelfde prijs met btw, op twee decimalen, als tekst. |
advice_price |
number|null | De adviesprijs, als de leverancier die doorgeeft. |
wholesale_price |
number|null | De groothandelsprijs, als de leverancier die doorgeeft. |
category |
string|null | De categorie bij dit aanbod. |
ingredients |
array | Ingrediënten volgens de leverancier. |
attributes |
array | Kenmerken volgens de leverancier. |
nutrition |
array | Voedingswaarden volgens de leverancier. |
description |
string|null | De beschrijving van de leverancier. Kan HTML bevatten. |
clean_description |
string|null | De beschrijving van de leverancier zonder opmaak. |
images |
array | De afbeeldingen van de leverancier, als volledige internetadressen. |
Heeft een product voor een veld geen waarde, dan staat het veld er toch, met null of een lege lijst.
Geen eigen prijs bij Producten
Dit adres toont de prijzen van de leveranciers. Jouw eigen prijs en voorraad per klantartikel staan bij Mijn producten.