Proxy-seller

Webhook

Updated:

Invece di effettuare il polling, è possibile ricevere gli eventi di un ordine sul proprio endpoint HTTPS. I webhook trasmettono gli stessi eventi di Ordine degli eventi. Il registro degli eventi rimane disponibile sia con che senza webhook, quindi è sempre possibile ricorrere al polling.

Configurazione

  • Approvato callback_url in Effettua un ordine, oppure impostalo in un secondo momento con Ordine di aggiornamento.

  • La risposta restituisce webhook_secret (whsec_…) una volta sola. Salvarla: serve a firmare ogni webhook.

  • Modifica callback_url emette un nuovo segreto. Il segreto precedente continua a firmare i webhook per 24 ore: durante questo periodo X-PS-Signature presenta due firme.

Richiesta

Proprietà

Valore

Metodo

POST a callback_url

Intestazioni

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

Corpo del testo

Un evento, come in Ordine degli eventi; attempt è il numero del tentativo di consegna (1, 2, …)

Successo

Qualsiasi 2xx entro 5 secondi. I reindirizzamenti non vengono seguiti, il corpo della risposta non viene letto

Consegna

Almeno una volta, in ordine casuale. Eliminare i duplicati in base a 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"}}

Verifica la firma

X-PS-Signature: v1=hex(HMAC-SHA256(key, timestamp + "." + raw_body))

  • key — i byte (UTF-8) dell’intero webhook_secret stringa, compresa la whsec_ prefisso.

  • timestamp — il valore di X-PS-Timestamp, secondi Unix.

  • raw_body — il corpo del testo esattamente come ricevuto, prima di qualsiasi analisi JSON.

  • Nelle 24 ore successive a una modifica segreta, l'intestazione è v1=<current>,v1=<previous>: accetta la richiesta se uno qualsiasi di essi corrisponde.

  • Rifiuta le richieste il cui timestamp differisca dal tuo orologio di oltre 300 secondi.

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)));
}

Nuovi tentativi

Regola

Valore

Primo tentativo

Non prima di 30 secondi dopo l’evento

Nuovi tentativi

Dopo 1 min, 5 min, 30 min, 2 h, 6 h, 12 h e 24 h: 8 tentativi in circa 44,6 ore

Troppo vecchio

Un evento risalente a più di circa 45,6 ore fa non viene più inviato

Interruttore automatico

Dopo 3 fallimenti consecutivi, gli altri eventi dell’ordine attendono il prossimo tentativo

Disattivazione

Se l’ultimo tentativo di un evento fallisce e l’URL non ha accettato alcun webhook da quando tale evento è stato creato, l’invio all’URL viene disabilitato. L’ordine stesso non ne risente

Per abilitare un URL disabilitato, inviarlo nuovamente con Ordine di aggiornamento: lo stesso URL al massimo una volta all’ora, un nuovo URL in qualsiasi momento. Gli eventi mancati sono sempre in Ordine degli eventi.

Regole relative a callback_url

Verificato al momento dell’emissione del preventivo e in PATCH. Una violazione comporta 400 invalid_request:

Regola

dettaglio

ASCII stampabile, fino a 2048 caratteri

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

https solo

/callback_url: only https is allowed

Nessun nome utente o password nell’URL

/callback_url: credentials in URL are not allowed

Nessun frammento

/callback_url: fragment is not allowed

Solo porta 443

/callback_url: only port 443 is allowed

Un nome DNS pubblico, oppure un indirizzo IPv4 canonico, oppure un indirizzo IPv6 tra parentesi

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

Tutti gli indirizzi dell’host sono pubblici

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

Non un host del servizio stesso

/callback_url: host is not allowed

Il DNS viene ricontrollato prima di ogni consegna; la richiesta viene inviata solo agli indirizzi verificati.

On this page

Webhook | Proxy-seller