Webhooks
Lors de l'utilisation de delivery_mode: webhook, Apertur envoie les images par POST à votre point de terminaison dès qu'elles sont traitées.
En-têtes de requête
| En-tête | Description |
|---|---|
| X-Aptr-Signature | Signature HMAC-SHA256 du corps de la requête |
| X-Aptr-Session-Id | L'identifiant de la session d'envoi |
| X-Aptr-Image-Index | Index basé sur 0 de cette image dans la session |
| X-Aptr-Image-Id | Identifiant unique de l'image |
| Content-Type | Dépend du format : multipart/form-data, application/json ou application/octet-stream |
Formats de webhook
multipart(par défaut)
L'image est envoyée sous forme de POST multipart/form-data. Le nom du champ de fichier est image. Les tags de la session sont inclus comme champs de formulaire additionnels.
Content-Type: multipart/form-data; boundary=----AptrBoundary ------AptrBoundary Content-Disposition: form-data; name="image"; filename="photo.jpg" Content-Type: image/jpeg <binary image data> ------AptrBoundary Content-Disposition: form-data; name="user_id" usr_abc123 ------AptrBoundary--
json_base64
L'image est encodée en base64 et incluse dans un corps JSON avec les métadonnées et les tags.
{
"session_id": "sess_01HX...",
"image_id": "img_01HX...",
"image_index": 0,
"mime_type": "image/jpeg",
"filename": "photo.jpg",
"size_bytes": 245000,
"data": "base64-encoded-image-data...",
"tags": {
"user_id": "usr_abc123"
}
}binary
Les octets bruts de l'image sont envoyés comme corps de la requête avec Content-Type: application/octet-stream. Les métadonnées ne sont disponibles que dans les en-têtes.
Vérification de la signature HMAC
Chaque requête de webhook inclut un en-tête X-Aptr-Signature. La valeur est sha256=<hex-digest> calculée sur le corps brut de la requête à l'aide du secret webhook de votre projet.
Trouvez votre secret webhook dans Tableau de bord → Projet → Paramètres.
const crypto = require("crypto");
function verifySignature(body, signatureHeader, secret) {
const expected = "sha256=" +
crypto.createHmac("sha256", secret).update(body).digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected, "utf8"),
Buffer.from(signatureHeader, "utf8")
);
}
// Express.js example
app.post("/webhook", express.raw({ type: "*/*" }), (req, res) => {
const sig = req.headers["x-aptr-signature"];
if (!verifySignature(req.body, sig, process.env.APTR_WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
// Process image...
res.status(200).end();
});Note de sécurité
Lisez toujours le corps brut de la requête avant de le parser. Parser d'abord (par exemple, avec un middleware JSON) peut altérer les octets du corps et faire échouer la vérification de la signature.
Politique de nouvelles tentatives
Une livraison de webhook est considérée comme échouée si votre serveur retourne un code de statut non-2xx ou ne répond pas dans les 30 secondes. Les livraisons échouées sont retentées avec un délai exponentiel :
| Tentative | Délai après la précédente |
|---|---|
| 1re nouvelle tentative | 30 secondes |
| 2e nouvelle tentative | 5 minutes |
| 3e nouvelle tentative | 30 minutes |
| 4e nouvelle tentative | 2 heures |
| 5e nouvelle tentative | 6 heures |
Des tentatives supplémentaires continuent jusqu'à l'épuisement du nombre maximal de jours de nouvelles tentatives de votre plan. Lorsque toutes les tentatives échouent, vous recevez un courriel de notification d'échec.