Se connecter

← Intégrations

Lien générique (webhook) : envoyer les ventes à Stokyo

Avec le webhook générique, toute caisse, boutique en ligne ou intégrateur envoie ses ventes à Stokyo, qui les déduit automatiquement du stock. Cette page s’adresse à la personne qui construit le lien.

1. Adresse et clé secrète

L’exploitant les trouve dans Stokyo sous Plus → Connexions → Lien générique → Afficher l’adresse et la clé. Chaque commerce reçoit sa propre adresse (se termine par /pos-webhook/ep_…) et sa propre clé secrète (commence par whsec_). Gardez la clé uniquement sur le serveur, jamais dans une appli ou une page web.

2. Envoyer une vente

Envoyez un POST avec un corps JSON. Un seul événement (sans liste events) ou jusqu’à 100 à la fois.

POST https://tcphaxqfzdfgvkxixbzk.supabase.co/functions/v1/pos-webhook/ep_…
Content-Type: application/json
Stokyo-Signature: t=1793400000,v1=5f2b…c91e

{
  "events": [
    {
      "ticketId": "1287",
      "type": "sale",
      "occurredAt": "2026-10-30T21:14:00+01:00",
      "lines": [
        { "itemId": "PILS25", "name": "Pils 25 cl", "qty": 2, "unitPrice": 3.20, "barcode": "5410228142218" },
        { "itemId": "MOJ", "name": "Mojito", "qty": 1, "unitPrice": 9.50 }
      ]
    }
  ]
}

3. Champs

ChampObligatoireExplication
ticketIdouiIdentifiant unique du ticket dans la caisse. Renvoyer le même ticket n’encode rien en double.
typenonsale (par défaut), refund (retour) ou void (annulation d’un ticket entier).
occurredAtnonMoment de la vente au format ISO 8601, avec fuseau horaire. Vide = maintenant.
refundOfnonPour refund ou void : le ticketId d’origine.
lines[].itemIdun des troisIdentifiant de l’article dans la caisse (PLU, SKU). Stokyo retient à quel produit il est lié.
lines[].barcodeun des troisCode EAN. S’il correspond à un produit Stokyo, le lien est fait automatiquement.
lines[].nameun des troisNom tel que sur le ticket. Sert aux suggestions lors de la liaison.
lines[].qtyouiQuantité, supérieure à 0. Positive aussi pour un retour.
lines[].unitPricenonPrix de vente unitaire, à titre d’information.

4. Signer (HMAC-SHA256)

Chaque requête contient l’en-tête Stokyo-Signature: t=<secondes unix>,v1=<hex>. v1 est le HMAC-SHA256 de <t>.<corps brut> avec la clé secrète. Signez exactement les octets envoyés. L’horodatage peut s’écarter de 5 minutes au maximum, pour qu’une requête interceptée ne puisse pas être rejouée.

Node.js

import crypto from "node:crypto";

const body = JSON.stringify(payload);            // send exactly this text
const t = Math.floor(Date.now() / 1000);
const v1 = crypto.createHmac("sha256", SECRET).update(`${t}.${body}`).digest("hex");

await fetch(URL, {
  method: "POST",
  headers: { "Content-Type": "application/json", "Stokyo-Signature": `t=${t},v1=${v1}` },
  body,
});

Python

import hmac, hashlib, json, time, requests

body = json.dumps(payload, separators=(",", ":"))
t = int(time.time())
v1 = hmac.new(SECRET.encode(), f"{t}.{body}".encode(), hashlib.sha256).hexdigest()
requests.post(URL, data=body, headers={
    "Content-Type": "application/json",
    "Stokyo-Signature": f"t={t},v1={v1}",
})

Shell (curl)

BODY='{"events":[{"ticketId":"T-1","lines":[{"itemId":"PILS25","qty":1}]}]}'
T=$(date +%s)
SIG=$(printf '%s' "$T.$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')
curl -X POST "$URL" -H "Content-Type: application/json" \
     -H "Stokyo-Signature: t=$T,v1=$SIG" --data "$BODY"

5. Retours et annulations

Un refund remet les quantités indiquées en stock. Un void annule tout ce qui a été encodé pour le ticket d’origine. Si une annulation arrive avant le ticket lui-même, Stokyo attend et la traite dès que le ticket est là.

{ "events": [
  { "ticketId": "1288", "type": "refund", "refundOf": "1287",
    "lines": [ { "itemId": "PILS25", "qty": 1 } ] },
  { "ticketId": "1287", "type": "void" }
] }

6. Réponses

200 signifie : enregistré en toute sécurité. La réponse indique ce qui s’est passé :

{ "ok": true, "accepted": 1, "duplicates": 0, "booked": 1, "needsMapping": 0, "waiting": 0, "queuedForRetry": 0 }
CodeSignificationQue faire
401Signature absente, incorrecte ou trop ancienneVérifier la clé et l’horloge. Ne pas renvoyer sans correction.
404Adresse inconnueRecopier l’adresse depuis Stokyo.
400 / 422JSON invalide ou champs incorrects (details indique lesquels)Corriger le corps.
413Trop grand (plus de 100 événements ou 1 Mo)Découper.
503Temporairement indisponibleRéessayer, p. ex. après 1, 5 et 30 minutes. Un double envoi ne pose aucun problème.

7. Bon à savoir