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

ParameterTypeVerplichtStandaardBeschrijving
affordablebooleanNeefalseGeeft 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
identifierstringNeeEen 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

VeldBeschrijving
remaining_stockInwisselingen die nog over zijn. null betekent onbeperkt.
total_stockAantal inwisselingen waarmee de beloning begon. null betekent onbeperkt.
available_fromYYYY-MM-DD, geen timestamp. Deze twee datums zijn de uitzondering op deze API
available_untilYYYY-MM-DD. null betekent dat de beloning niet verloopt.
branchesDe 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

ParameterTypeVerplichtBeschrijving
branchstringNeeJe 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

VeldTypeBeschrijving
familystringtransaction (getriggerd door een aankoop) of customer_moment (getriggerd door de klant)
momentstring|nullVoor customer_moment: birthday, anniversary, first_purchase, nth_purchase of win_back
configobject|nullInstellingen per familie. Zie hieronder
versionintegerGaat omhoog bij elke inhoudelijke wijziging. Wordt meegegeven aan de punten die een aankoop oplevert.
multiplierinteger|nullHeel getal, minimaal 2: 2 = 2x, 3 = 3x. null tenzij deze campagne met een vermenigvuldiger werkt.
recurrence_typestring|nulldate_range, days_of_week of specific_dates. null wanneer de campagne geen schema heeft.
recurrence_configobject|nullInstellingen bij het herhalingstype. null wanneer de campagne zich niet herhaalt.
schedule_summarystringHet schema in gewone taal. "Always active" wanneer de campagne zich niet herhaalt. De server vertaalt het niet.
starts_atstringKalenderdatum, YYYY-MM-DD
ends_atstring|nullKalenderdatum, YYYY-MM-DD. null betekent: geen einddatum.
statusobject{ "value": "active", "label": "Active" }. label is altijd Engels. Zie hieronder
min_transaction_amountnumber|nullMinimale aankoop waarbij de campagne geldt, in euro's. Zie hieronder
branchesarray|nullDe filialen waar deze campagne loopt, elk { "external_id", "name", "type" }. null betekent alle filialen. Zie hieronder
created_atstring|nullISO 8601-timestamp
updated_atstring|nullISO 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":

SleutelBeschrijving
scopewhole_purchase of products
reward_typemultiplier (gebruikt het veld multiplier) of fixed_points (gebruikt points)
pointsPunten per eenheid die meetelt, bij fixed_points
max_points_per_purchaseMaximum dat één aankoop met deze campagne kan opleveren. Ontbreekt hij of is hij null, dan is er geen limiet.
productsBij products-bereik: een vaste momentopname van { "sku", "name" }-paren
combineerbaartrue 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

CodeStatusBeschrijving
BRANCH_NOT_FOUND422branch 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