API-documentatie
De OrangeHub dealer-API levert per dealer een actuele, verrijkte catalogus van Orange Office producten — met dealer-specifieke nettoprijzen.
- Base URL
- https://orangehub.cyboxlabs.nl/api/v1
- Auth
- Bearer token
- Format
- JSON
Authenticatie
Elke request vereist een persoonlijke Sanctum-toegangstoken in de
Authorization-header.
Tokens worden door een OrangeHub-beheerder aangemaakt in het admin-panel onder de dealer
(API-tokens → Genereer token). De plain-text token wordt eenmalig getoond; bij verlies moet er een nieuw token worden gegenereerd.
GET https://orangehub.cyboxlabs.nl/api/v1/products HTTP/1.1
Authorization: Bearer <plain-text-token>
Accept: application/json
| Foutsituatie | Status | Body |
|---|---|---|
| Geen of foutief token | 401 | {"message":"Unauthenticated."} |
| Ingetrokken token | 401 | {"message":"Unauthenticated."} |
| Dealer gedeactiveerd | 401 | {"message":"Dealer is not active."} |
/products
Gepagineerde lijst van actieve producten — inclusief verrijking, afbeeldingen, documenten en dealer-specifieke nettoprijs.
Parameters
| Naam | Type | Default | Toelichting |
|---|---|---|---|
| product_group_id | int | — | Filter op productgroep (lokaal id). |
| per_page | int | 50 | Tussen 1 en 200. |
| page | int | 1 | Standaard Laravel-paginering. |
cURL
curl -s \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json" \
"https://orangehub.cyboxlabs.nl/api/v1/products?per_page=10"
Voorbeeldrespons
{
"data": [
{
"external_id": "DVD",
"sku": "DVD",
"name": "Kabel doorvoerdop boormaat Ø 60mm",
"description": "<p>...</p>",
"manufacturer": "Orange Office",
"currency": "EUR",
"parent_sku": null,
"prices": { "base": 19.0, "override": null, "net": 16.15 },
"dimensions": { "length_mm": 72, "width_mm": 72, "height_mm": 19 },
"weight_grams": 50,
"enriched_content": "<p>...</p>",
"product_group": {
"external_id": "OO-cat-1318",
"name": "Losse componenten",
"parent_id": 1
},
"images": [
{
"url": "https://.../storage/products/12/images/DVD-1.jpg",
"alt_text": null,
"sort_order": 0,
"is_primary": true
}
],
"documents": [
{
"url": "https://.../storage/products/12/documents/handleiding.pdf",
"label": "Handleiding",
"original_filename": "handleiding.pdf",
"sort_order": 0
}
],
"custom_fields": {
"eu_energy_label": { "value": "A++", "label": "EU Energielabel", "type": "text", "unit": null },
"power_draw": { "value": 1500, "label": "Vermogen", "type": "integer", "unit": "W" }
}
}
],
"links": { "first": "...", "last": "...", "prev": null, "next": "..." },
"meta": { "current_page": 1, "per_page": 50, "total": 30, "last_page": 1 }
}
/products/{sku}
Eén product opvragen via zijn SKU. Identieke shape als één element uit /products, maar dan onder data.
Parameters
| Naam | Type | Default | Toelichting |
|---|---|---|---|
| sku | string | — | SKU van het product (mag forward slashes bevatten). |
cURL
curl -s \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json" \
"https://orangehub.cyboxlabs.nl/api/v1/products/DVD"
Voorbeeldrespons
{
"data": {
"external_id": "DVD",
"sku": "DVD",
"name": "Kabel doorvoerdop boormaat Ø 60mm",
"prices": { "base": 19.0, "override": null, "net": 16.15 },
"...": "..."
}
}
Foutresponses
| Foutsituatie | Status | Body |
|---|---|---|
| SKU onbekend | 404 | {"message":"Product not found."} |
| SKU bestaat, maar product staat niet op Actief in dealer-API | 404 | {"message":"Product is not available in the dealer-API."} |
/product-groups
De volledige productgroep-boom — alleen root-groepen op het hoogste niveau, met children recursief.
cURL
curl -s \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json" \
"https://orangehub.cyboxlabs.nl/api/v1/product-groups"
Voorbeeldrespons
{
"data": [
{
"external_id": "OO-cat-25",
"name": "Werkplekken",
"parent_id": null,
"children": [
{
"external_id": "OO-cat-1318",
"name": "Losse componenten",
"parent_id": 7,
"children": []
}
]
}
]
}
Pricing
Elk product bevat een
prices-object
met de basis-, override- en dealer-specifieke nettoprijs.
| Sleutel | Bron |
|---|---|
| base | base_price uit de feed. |
| override | price_override als een beheerder die handmatig heeft gezet, anders null. |
| net | Effectieve prijs (override of base) minus de dealer-korting die voor het product van toepassing is (productgroep-regel als die bestaat, anders de dealer-brede basis-korting). |
effective = override ?? base
discount = product_group_rule ?? dealer.base_discount_percentage
net = round(effective * (1 - discount / 100), 2)
De toegepaste korting wordt in deze volgorde bepaald: bestaat er voor de productgroep van het product een
DealerDiscount-regel,
dan wint die — ook als hij lager is dan de basis-korting. Anders gebruikt de API de
base_discount_percentage van de dealer (default
0).
Inactieve producten
(is_active = false)
verschijnen nooit in de API-uitvoer.
Custom fields
Naast de vaste velden kan een beheerder per product ad-hoc extra eigenschappen vastleggen. Die komen terug onder
custom_fields
als een object met dynamische sleutels — de sleutels verschillen per product, dus programmeer er defensief op.
Als een product geen extra velden heeft is het object leeg ({}).
| Sleutel per veld | Toelichting |
|---|---|
| value | De typed waarde — een string, integer, decimaal, boolean of null. |
| label | Mens-leesbare naam van het veld, door de beheerder ingegeven. |
| type | Eén van text, long_text, integer, decimal, boolean, select. |
| unit | Optionele eenheid/suffix (bv. "kg", "kWh"), of null. |
De volgorde van keys in custom_fields
reflecteert de volgorde die in het admin-panel is bepaald.