Proxy-seller

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_url dans 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 temps X-PS-Signature comporte deux signatures.

Demande

Propriété

Valeur

Méthode

POST à callback_url

En-têtes

Content-Type: application/json; charset=utf-8, User-Agent: ProxySeller-Webhooks/1, X-PS-Timestamp, X-PS-Signature

Corps du texte

Un événement, comme dans Ordre des événements; attempt correspond au numéro de tentative de livraison (1, 2, …)

Réussite

Tout 2xx dans les 5 secondes. Les redirections ne sont pas suivies, le corps de la réponse n'est pas lu

Livraison

Au moins une fois, dans un ordre aléatoire. Supprimer les doublons en event_id

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'ensemble webhook_secret chaîne de caractères, y compris le whsec_ préfixe.

  • timestamp — la valeur de X-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

/callback_url: must be a printable URL up to 2048 characters

https uniquement

/callback_url: only https is allowed

Pas d'identifiant ni de mot de passe dans l'URL

/callback_url: credentials in URL are not allowed

Pas de fragment

/callback_url: fragment is not allowed

Port 443 uniquement

/callback_url: only port 443 is allowed

Un nom DNS public, une adresse IPv4 canonique ou une adresse IPv6 entre crochets

/callback_url: host must be a public DNS name, /callback_url: IPv4 address must be a canonical dotted quad

Toutes les adresses de l'hébergeur sont publiques

/callback_url: host resolves to a private or reserved address, /callback_url: host does not resolve

Il ne s'agit pas de l'hébergeur du service lui-même

/callback_url: host is not allowed

Le DNS est vérifié à nouveau avant chaque envoi ; la requête est envoyée uniquement aux adresses vérifiées.

On this page

Webhooks | Proxy-seller