Webhooks
Updated:
Au lieu d'effectuer des requêtes de sondage, vous pouvez recevoir les événements liés à une commande sur votre point de terminaison HTTPS. Les webhooks transmettent les mêmes événements que Ordre des événements. Le journal des événements reste accessible avec ou sans webhooks ; vous pouvez donc toujours recourir à l'interrogation régulière.
Mise en place
Refusé
callback_urldans Passer une commande, ou définissez-le plus tard avec Ordre de mise à jour.La réponse renvoie
webhook_secret(whsec_…) une seule fois. Enregistrez-le : il signe chaque webhook.Modification
callback_urlémet un nouveau secret. L'ancien secret continue de signer les webhooks pendant 24 heures : pendant ce laps de tempsX-PS-Signaturecomporte deux signatures.
Demande
Propriété | Valeur |
|---|---|
Méthode |
|
En-têtes |
|
Corps du texte | Un événement, comme dans Ordre des événements; |
Réussite | Tout |
Livraison | Au moins une fois, dans un ordre aléatoire. Supprimer les doublons en |
POST /hooks/proxy HTTP/1.1
Host: agent.example.com
Content-Type: application/json; charset=utf-8
User-Agent: ProxySeller-Webhooks/1
X-PS-Timestamp: 1762077838
X-PS-Signature: v1=5f0c2a…9e
{"event_id":"evt_01JZ8QA2C4E6G8J0K2M4P6R8T0","type":"order.active","created_at":"2026-11-02T10:03:58Z","api_version":"v1","order_id":"ord_01JZ8Q7K5N2R4T6V8X0Z2B4D6F","wallet":"0x857b06519e91e3a54538791bdbb0e22373e36b66","attempt":1,"data":{"lines":[{"line_id":"1","status":"active","delivered":2,"qty":2}],"expires_at":"2026-12-02T23:59:59Z"}}Vérifier la signature
X-PS-Signature: v1=hex(HMAC-SHA256(key, timestamp + "." + raw_body))
key— les octets (UTF-8) de l'ensemblewebhook_secretchaîne de caractères, y compris lewhsec_préfixe.timestamp— la valeur deX-PS-Timestamp, secondes Unix.raw_body— le corps du message tel qu’il a été reçu, avant toute analyse JSON.Pendant les 24 heures suivant une modification secrète, l'en-tête est
v1=<current>,v1=<previous>: acceptez la demande si l'un d'entre eux correspond.Refusez les demandes dont l'horodatage diffère de plus de 300 secondes par rapport à votre horloge.
Python
import hashlib
import hmac
import time
def verify(secret: str, timestamp: str, signature_header: str, raw_body: bytes, tolerance: int = 300) -> bool:
if abs(time.time() - int(timestamp)) > tolerance:
return False
expected = hmac.new(secret.encode(), timestamp.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
candidates = [part.strip()[3:] for part in signature_header.split(",") if part.strip().startswith("v1=")]
return any(hmac.compare_digest(expected, candidate) for candidate in candidates)Node.js
import crypto from 'node:crypto';
function verify(secret, timestamp, signatureHeader, rawBody, toleranceSeconds = 300) {
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > toleranceSeconds) return false;
const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.`).update(rawBody).digest('hex');
return signatureHeader.split(',').map((s) => s.trim()).filter((s) => s.startsWith('v1='))
.some((s) => s.length === expected.length + 3
&& crypto.timingSafeEqual(Buffer.from(s.slice(3)), Buffer.from(expected)));
}Nouvelles tentatives
Règle | Valeur |
|---|---|
Première ébauche | Au plus tôt 30 secondes après l'événement |
Nouvelles tentatives | Après 1 min, 5 min, 30 min, 2 h, 6 h, 12 h et 24 h : 8 tentatives en environ 44,6 heures |
Trop ancien | Un événement datant de plus de 45,6 heures environ n'est plus envoyé. |
Disjoncteur | Après 3 échecs consécutifs, les autres événements de la séquence attendent la prochaine tentative |
Désactivation | Si la dernière tentative d'un événement échoue et que l'URL n'a accepté aucun webhook depuis la création de cet événement, la transmission vers l'URL est désactivée. La commande elle-même n'est pas affectée. |
Pour réactiver une URL désactivée, renvoyez-la avec Ordre de mise à jour: la même URL au maximum une fois par heure, une nouvelle URL à tout moment. Les événements manqués sont toujours dans Ordre des événements.
Règles relatives à l'URL de rappel
Vérifié lors de l'émission du devis et dans PATCH. Toute infraction entraîne 400 invalid_request:
Règle | détail |
|---|---|
ASCII imprimable, jusqu'à 2 048 caractères |
|
|
|
Pas d'identifiant ni de mot de passe dans l'URL |
|
Pas de fragment |
|
Port 443 uniquement |
|
Un nom DNS public, une adresse IPv4 canonique ou une adresse IPv6 entre crochets |
|
Toutes les adresses de l'hébergeur sont publiques |
|
Il ne s'agit pas de l'hébergeur du service lui-même |
|
Le DNS est vérifié à nouveau avant chaque envoi ; la requête est envoyée uniquement aux adresses vérifiées.