Skip to content
StampyWalletDocs
API and webhooks / Webhooks / Events

Event list

The nine events sent by StampyWallet webhooks, when they are sent, and the exact content of their donnees field.

Every event has the same envelope (id, type, cree_le, commerce, see Webhooks). Only donnees changes; it is shown on its own below. Events are sent from the counter as well as from the API: a visit scanned or added through POST /v1/passages produces the same passage.cree.

EventSent when
client.creeA customer joins the program (their card is created)
carte.ajouteeThe customer saves their card in Apple Wallet or Google Wallet
passage.creeA visit is added: one or more stamps, or points
passage.annuleA customer's last visit is cancelled
recompense.atteinteA visit crosses a tier: a reward is due (one per tier crossed)
recompense.offerteThe reward is handed to the customer
recompense.annuleeHanding over a reward is cancelled: it is due again
carte_cadeau.vendueA gift card is sold
forfait.venduA prepaid package is sold

Note : carte.ajoutee covers Apple Wallet and Google Wallet: donnees.carte.wallet is apple or google. On Apple, the event is sent for each new device (an iPhone then a watch produce two). Removing the card sends nothing.

client.cree

donnees
{
  "client": {
    "id": "3374a06e-9608-4376-91cb-1a3fb6721b04",
    "prenom": "Camille",
    "cree_le": "2026-10-22T05:52:45.664Z"
  }
}

telephone and email only appear if the customer gave them. prenom can be null.

carte.ajoutee

donnees
{
  "client": { "id": "40de4b86-1d7a-4cc6-add3-b7a83fa43c04", "prenom": "Inès",
              "telephone": "+33611223344", "email": "ines@example.com" },
  "carte": { "wallet": "apple" }
}

passage.cree

donnees
{
  "client": { "id": "40de4b86-1d7a-4cc6-add3-b7a83fa43c04", "prenom": "Inès",
              "telephone": "+33611223344", "email": "ines@example.com" },
  "passage": {
    "id": "226fdea1-ba59-49fb-93e6-60a14a765134",
    "quantite": 1,
    "montant": null,
    "devise": "EUR",
    "reference": "caisse-1",
    "source": "scan",
    "piste": "normal",
    "tampons": 1,
    "objectif": 2
  }
}
  • quantite: what the visit is worth (stamps, or points in points mode).
  • montant: the receipt amount in cents if it was entered, otherwise null.
  • reference: the operation identifier sent by the caller (the API reference, or the counter's), otherwise null.
  • source: scan, manuel, api…
  • piste: normal, or premium for the second counter.
  • tampons (or points in points mode) and objectif: the counter after the visit. A visit that completes the card returns the next card's counter (often 0); the reward comes in a separate recompense.atteinte.

passage.annule

donnees
{
  "client": { "id": "40de4b86-1d7a-4cc6-add3-b7a83fa43c04", "prenom": "Inès",
              "telephone": "+33611223344", "email": "ines@example.com" },
  "passage": {
    "id": "d8f62d77-88a6-44ef-a0c3-2a7d5066b90a",
    "quantite": 1,
    "source": "scan",
    "piste": "normal",
    "tampons": 0,
    "objectif": 2
  },
  "recompenses_retirees": 0,
  "motif": "scanned twice"
}

passage.id is the one from the original passage.cree, and the counter is the one after the cancellation. recompenses_retirees: the rewards this visit had unlocked and that disappear with it. motif: the reason entered at the counter, or null.

recompense.atteinte

donnees
{
  "client": { "id": "40de4b86-1d7a-4cc6-add3-b7a83fa43c04", "prenom": "Inès",
              "telephone": "+33611223344", "email": "ines@example.com" },
  "recompense": {
    "id": "504c8734-3bbd-4fe9-95f8-7a67c8239dab",
    "libelle": "A free coffee",
    "palier": 2,
    "piste": "normal",
    "expire_le": null
  },
  "passage_id": "8bfbdd5e-eff4-4a3b-94fe-1557ec6edce6"
}

One event per tier crossed. expire_le is null if the business's rewards don't expire.

recompense.offerte

donnees
{
  "client": { "id": "40de4b86-1d7a-4cc6-add3-b7a83fa43c04", "prenom": "Inès",
              "telephone": "+33611223344", "email": "ines@example.com" },
  "recompense": {
    "id": "504c8734-3bbd-4fe9-95f8-7a67c8239dab",
    "libelle": "A free coffee",
    "piste": "normal",
    "offerte_le": "2026-10-22T05:54:51.790Z"
  }
}

recompense.annulee

donnees
{
  "client": { "id": "40de4b86-1d7a-4cc6-add3-b7a83fa43c04", "prenom": "Inès",
              "telephone": "+33611223344", "email": "ines@example.com" },
  "recompense": {
    "id": "504c8734-3bbd-4fe9-95f8-7a67c8239dab",
    "libelle": "A free coffee",
    "piste": "normal"
  },
  "motif": "wrong card"
}

carte_cadeau.vendue

donnees
{
  "client": null,
  "carte_cadeau": {
    "id": "ac7e56a5-3c00-492f-971a-21ca7d675fd6",
    "code": "EJ9Y-7FYN",
    "sorte": "montant",
    "produit": null,
    "montant": 2500,
    "devise": "EUR",
    "pour": "Lucie",
    "de": "Marc",
    "canal": "comptoir",
    "expire_le": "2027-04-22T05:54:51.879Z"
  }
}

sorte is montant or produit (then produit carries its name and montant its price). Here, 2500 cents: €25.

Warning : code is the gift card code, the one in its QR code: it is enough to redeem it at the counter. Treat it as a secret: don't write it in a shared spreadsheet or in logs.

forfait.vendu

donnees
{
  "client": null,
  "forfait": {
    "id": "0ec29323-ed13-4e6b-9595-963601290eac",
    "code": "XFF2-WTW9",
    "nom": "10 coffees",
    "unites": 10,
    "prix": 3000,
    "devise": "EUR",
    "titulaire": "Paul",
    "canal": "comptoir",
    "expire_le": "2027-04-22T05:54:51.891Z"
  }
}

titulaire: the name written at the sale, or null. expire_le is null for a package with no expiry date. As with a gift card, keep code secret.

Note : personal data is limited to what the customer gave when signing up. Once received, it is your responsibility: only keep it as long as necessary.

Updated

Was this page helpful?