Skip to content
StampyWalletDocs
API and webhooks / POS systems / Receive your POS

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.

POST/v1/entrants/:jeton

An 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:

SourceWhat countsCustomerAmountReference
squarepayment.created / payment.updated with status COMPLETEDBuyer's email, or the customer's email and phoneExcluding tipThe payment id
shopifyorders/paidEmail and phone of the customer or the orderOrder subtotalThe order id
sumup (beta)PAID or SUCCESSFUL transactionEmail or phoneTransaction amountTransaction code
zettle (beta)PurchaseCreatedCustomer's email or phonePurchase amountThe purchase id
generiqueThe body of POST /v1/passagesclientmontantreference (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.

SourceHeaderSignature
generiqueX-Stampy-SignatureHex HMAC-SHA256 of the raw body, with the address key (sha256= prefix accepted)
squarex-square-hmacsha256-signatureBase64 HMAC-SHA256 of the notification URL followed by the raw body
shopifyX-Shopify-Hmac-Sha256Base64 HMAC-SHA256 of the raw body
sumupX-Payload-SignatureHex HMAC-SHA256 of the raw body
zettleX-iZettle-SignatureHex 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"

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

Was this page helpful?