Receive events from your POS
POST /v1/entrants/:jeton receives sales from Square, Shopify, SumUp, Zettle or any tool, and adds the visit to the right customer.
/v1/entrants/:jetonAn address to give your POS: on every paid sale, the POS calls it, and StampyWallet adds the visit to the customer's card, found by their email or phone. No key to write into the POS: the address token is enough. An unknown or revoked address responds 404.
Sources
Each address is created for one source in Settings › Integrations, with an optional signing key. StampyWallet then reads that POS's format as is:
| Source | What counts | Customer | Amount | Reference |
|---|---|---|---|---|
square | payment.created / payment.updated with status COMPLETED | Buyer's email, or the customer's email and phone | Excluding tip | The payment id |
shopify | orders/paid | Email and phone of the customer or the order | Order subtotal | The order id |
sumup (beta) | PAID or SUCCESSFUL transaction | Email or phone | Transaction amount | Transaction code |
zettle (beta) | PurchaseCreated | Customer's email or phone | Purchase amount | The purchase id |
generique | The body of POST /v1/passages | client | montant | reference (optional) |
Note : POS sources never create a customer: a sale with no known customer is ignored. A sale with no email or phone, or with no reference, is ignored too. Only the generique source can create a customer, with creer_si_absent: true.
Signature
When a signing key is saved for the address, every call must be signed, otherwise 401 signature_invalide. Always paste it in when the POS provides one.
| Source | Header | Signature |
|---|---|---|
generique | X-Stampy-Signature | Hex HMAC-SHA256 of the raw body, with the address key (sha256= prefix accepted) |
square | x-square-hmacsha256-signature | Base64 HMAC-SHA256 of the notification URL followed by the raw body |
shopify | X-Shopify-Hmac-Sha256 | Base64 HMAC-SHA256 of the raw body |
sumup | X-Payload-Signature | Hex HMAC-SHA256 of the raw body |
zettle | X-iZettle-Signature | Hex HMAC-SHA256 of timestamp + "." + payload |
The generic format
For a script, a no-code tool or a POS with no known format, send the same body as POST /v1/passages:
corps='{"client": {"telephone": "+33612345678"}, "montant": 18.9, "reference": "T-2026-1025-0091"}'
signature=$(printf '%s' "$corps" | openssl dgst -sha256 -hmac "$STAMPY_ENTRANT_SECRET" | sed 's/^.* //')
curl https://app.stampywallet.com/v1/entrants/9QkT2vX7pL4mR8sN1bC6dF3gH5jK0wYz \
-H "Content-Type: application/json" \
-H "X-Stampy-Signature: $signature" \
-d "$corps"const crypto = require('node:crypto');
const corps = JSON.stringify({ client: { telephone: '+33612345678' }, montant: 18.9, reference: 'T-2026-1025-0091' });
const signature = crypto.createHmac('sha256', process.env.STAMPY_ENTRANT_SECRET).update(corps).digest('hex');
await fetch(process.env.STAMPY_ENTRANT_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Stampy-Signature': signature },
body: corps,
});Responses
Once the call is authenticated, the response is always 200, so the POS learns nothing about your customer list:
{ "ok": true, "ignore": true }: the event is not relevant (not paid, another topic, no customer, or no reference for a POS);{ "ok": true }: in every other case, whether the customer exists or not, whether the visit was added or refused (too soon, amount too small).
Only a real outage responds 500: the POS retries, and the reference ensures a new attempt does not add a stamp twice. Each address accepts 300 calls per minute.
Step-by-step settings, POS by POS: Connect your POS.
Updated