API-referentie
Beloningen-endpoints
Met deze endpoints haal je de beschikbare beloningen en de actieve campagnes op.
Beloningen weergeven
GET /api/v1/rewards
Haal de beloningen op die nu actief zijn, binnen hun beschikbaarheidsperiode vallen en nog
voorraad hebben. Deze lijst is niet gepagineerd: data is de kale array, anders dan bij
elk ander lijst-endpoint op deze API.
Queryparameters
| Parameter | Type | Verplicht | Standaard | Beschrijving |
|---|---|---|---|---|
affordable | boolean | Nee | false | Geeft alleen de beloningen terug die de klant kan betalen. Dit heeft identifier nodig: hoort daar geen klant of geen wallet bij, dan krijg je de hele catalogus ongefilterd terug |
identifier | string | Nee | — | Een klantenkaartcode of een andere identifier. Hiermee zoekt Puntjes het saldo op waarop affordable filtert |
Response
{
"data": [
{
"id": 1,
"name": "10% Discount",
"description": "Get 10% off your next purchase",
"type": "discount",
"point_cost": 500,
"image_url": "string",
"remaining_stock": 50,
"total_stock": 0,
"available_from": "2026-03-01",
"available_until": "2026-12-31",
"branches": [
{
"external_id": "shop-1",
"name": "Gent",
"type": "physical"
}
]
}
]
}
Responsevelden
| Veld | Beschrijving |
|---|---|
remaining_stock | Inwisselingen die nog over zijn. null betekent onbeperkt. |
total_stock | Aantal inwisselingen waarmee de beloning begon. null betekent onbeperkt. |
available_from | YYYY-MM-DD, geen timestamp. Deze twee datums zijn de uitzondering op deze API |
available_until | YYYY-MM-DD. null betekent dat de beloning niet verloopt. |
branches | De filialen waar de beloning kan worden ingewisseld, elk { "external_id", "name", "type" }, in de volgorde die jij aanhoudt. null betekent elk filiaal. |
Het typespecifieke detail van een beloning (de waarde van een korting, de referentie van
een gratis product) staat niet op dit endpoint. Dat krijg je als type_specific_data
terug zodra de beloning wordt ingewisseld; zie Inwisseling-endpoints.
Gefilterd op beschikbaarheid
Dit endpoint geeft alleen beloningen terug die nu beschikbaar zijn. Verlopen, uitverkochte en inactieve beloningen blijven eruit.
Campagnes weergeven
GET /api/v1/campaigns
Haal een gepagineerde lijst op van campagnes met de status actief: zowel de campagnes die al lopen als de campagnes die nog moeten beginnen.
Queryparameters
| Parameter | Type | Verplicht | Beschrijving |
|---|---|---|---|
branch | string | Nee | Je eigen sleutel voor één filiaal: de external_id die je het gaf, maximaal 64 tekens. Je krijgt de campagnes terug die daar lopen, dus de campagnes die aan dat filiaal hangen plus elke campagne die geen enkel filiaal noemt. Gebruik none voor de campagnes die gelden bij een aankoop zonder filiaal. Hoort de sleutel bij geen enkel filiaal van jou, dan volgt 422 BRANCH_NOT_FOUND in plaats van de ongefilterde lijst, zodat een typfout niet voor een rapport kan doorgaan |
Pagineren doe je met ?page=. De paginator leest die zelf uit de querystring, dus hij
staat niet in de parametertabel hierboven.
De paginagrootte ligt vast op 15
Dit endpoint negeert per_page. Van de lijst-endpoints accepteert alleen GET /products die parameter.
Breaking change: `multiplier` is nu nullable
multiplier was altijd een geheel getal. Hij is nu null bij campagnes rond een klantmoment en bij campagnes met
vaste punten. recurrence_type en recurrence_config werden in dezelfde wijziging nullable. Typeert je client alle
drie als altijd aanwezig, dan kan hij de twee campagnefamilies die er toen bij kwamen niet lezen. Verbreed die types
voordat je dit endpoint gebruikt.
De lijst is dubbel verpakt: de buitenste data is de standaard response-envelope, met daarin
de paginator. Campagnes staan dus op data.data.
Response
{
"data": {
"data": [
{
"id": 1,
"name": "10% Discount",
"family": "transaction",
"moment": null,
"config": [
{
"combineerbaar": false,
"reward_type": "multiplier",
"scope": "whole_purchase"
}
],
"version": 1,
"multiplier": 2,
"recurrence_type": "days_of_week",
"recurrence_config": [
{
"days": "saturday"
}
],
"schedule_summary": "Every Saturday and Sunday",
"starts_at": "2024-03-01",
"ends_at": "2024-06-30",
"status": {
"value": "active",
"label": "Active"
},
"min_transaction_amount": 25,
"branches": [
{
"external_id": "shop-1",
"name": "Gent",
"type": "physical"
}
],
"created_at": "2024-02-20T09:15:00+00:00",
"updated_at": "2024-02-20T09:15:00+00:00"
}
],
"links": {
"first": "https://puntjes.app/api/v1/campaigns?page=1",
"last": "https://puntjes.app/api/v1/campaigns?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 2
}
}
}
Responsevelden
| Veld | Type | Beschrijving |
|---|---|---|
family | string | transaction (getriggerd door een aankoop) of customer_moment (getriggerd door de klant) |
moment | string|null | Voor customer_moment: birthday, anniversary, first_purchase, nth_purchase of win_back |
config | object|null | Instellingen per familie. Zie hieronder |
version | integer | Gaat omhoog bij elke inhoudelijke wijziging. Wordt meegegeven aan de punten die een aankoop oplevert. |
multiplier | integer|null | Heel getal, minimaal 2: 2 = 2x, 3 = 3x. null tenzij deze campagne met een vermenigvuldiger werkt. |
recurrence_type | string|null | date_range, days_of_week of specific_dates. null wanneer de campagne geen schema heeft. |
recurrence_config | object|null | Instellingen bij het herhalingstype. null wanneer de campagne zich niet herhaalt. |
schedule_summary | string | Het schema in gewone taal. "Always active" wanneer de campagne zich niet herhaalt. De server vertaalt het niet. |
starts_at | string | Kalenderdatum, YYYY-MM-DD |
ends_at | string|null | Kalenderdatum, YYYY-MM-DD. null betekent: geen einddatum. |
status | object | { "value": "active", "label": "Active" }. label is altijd Engels. Zie hieronder |
min_transaction_amount | number|null | Minimale aankoop waarbij de campagne geldt, in euro's. Zie hieronder |
branches | array|null | De filialen waar deze campagne loopt, elk { "external_id", "name", "type" }. null betekent alle filialen. Zie hieronder |
created_at | string|null | ISO 8601-timestamp |
updated_at | string|null | ISO 8601-timestamp |
status.label is altijd Engels
Deze API kent geen taal per request en vertaalt niets aan de serverkant, dus staat er in label het Engelse woord,
welke taal je integratie ook spreekt. Vertaal value zelf, dat is active, inactive of completed, en precies
die drie vertaalt het Puntjes-portaal.
min_transaction_amount staat in euro's, niet in eurocenten
Dit is het enige veld op deze API dat niet in eurocenten staat. 25.0 betekent EUR 25,00, niet EUR 0,25. Elk ander
bedrag (total_amount, unit_price, price_cents en de statistiekcijfers) blijft een geheel aantal eurocenten.
Lees het bereik uit `branches`, niet uit `config.branch_ids`
branches bevat de external_id van elk filiaal waar de campagne loopt: de sleutel die je eigen systemen al
gebruiken. config.branch_ids beschrijft hetzelfde bereik met de interne sleutels van Puntjes. config gaat
ongewijzigd door zoals het is opgeslagen, en die ids zeggen buiten het portaal niets. branches is null wanneer
de campagne geen filiaal noemt; dan loopt hij overal, ook bij aankopen die zonder filiaal zijn geregistreerd. Een
lege array betekent het omgekeerde: de campagne heeft wel een bereik, maar elk filiaal dat hij noemde is intussen
verwijderd, dus hij komt nergens meer overeen.
Het config-object
Voor family: "transaction":
| Sleutel | Beschrijving |
|---|---|
scope | whole_purchase of products |
reward_type | multiplier (gebruikt het veld multiplier) of fixed_points (gebruikt points) |
points | Punten per eenheid die meetelt, bij fixed_points |
max_points_per_purchase | Maximum dat één aankoop met deze campagne kan opleveren. Ontbreekt hij of is hij null, dan is er geen limiet. |
products | Bij products-bereik: een vaste momentopname van { "sku", "name" }-paren |
combineerbaar | true wanneer deze campagne met andere mag stapelen. Anders betaalt alleen de sterkste uit |
Voor family: "customer_moment": de eigen instellingen van het moment (bijvoorbeeld every_n en
min_amount bij nth_purchase, years bij anniversary, months bij win_back) plus een
gift-object dat beschrijft wat het moment uitdeelt.
Campagnes van vóór dit contract
Een campagne uit een eerdere release kan een null of een onvolledige config hebben. Zo'n rij gedraagt zich als
een campagne met een vermenigvuldiger over de hele aankoop die niet mag stapelen. Lees de standaardwaarden en ga er
niet van uit dat de sleutels er staan.
Fouten
| Code | Status | Beschrijving |
|---|---|---|
BRANCH_NOT_FOUND | 422 | branch hoort bij geen enkel filiaal van jou, ook niet bij een gedeactiveerd filiaal. Puntjes weigert de filter in plaats van hem te negeren, zodat een verkeerd gespelde sleutel niet kan doorgaan voor een rapport over al je filialen |