Aller au contenu

Webhooks

Au lieu d’interroger, vous pouvez demander à Accessful d’envoyer par POST un événement signé à votre serveur dès qu’une tâche change d’état.

Il n’y a ni tableau de bord ni endpoint d’enregistrement. Vous attachez un callback à chaque téléversement, et vous choisissez vous-même le secret de signature — Accessful n’en émet aucun.

  • Téléversement multipart — envoyez les champs de formulaire webhookUrl et secret.
  • Téléversement par URL — envoyez les champs JSON callbackUrl et hmacSignature.
Fenêtre de terminal
curl -X POST "https://api.accessful.de/api/v1/upload-service/pdf/upload" \
-H "X-API-Key: $ACCESSFUL_API_KEY" \
-F "files=@document.pdf" \
-F "webhookUrl=https://votre-app.example.com/hooks/accessful" \
-F "secret=$VOTRE_WEBHOOK_SECRET"
type d’événementSe déclenche quand
case.runningLa tâche a commencé son traitement. Peut se déclencher plusieurs fois (une par itération).
case.completedLe résultat PDF/UA est prêt à être téléchargé.
case.failedLe traitement a échoué.
case.canceledLe cas a été annulé.
case.quota_exceededRejeté car le quota contractuel est épuisé.

Les états queued et quota_pending ne sont pas livrés en tant que webhooks.

Le corps de la requête est au format JSON. Content-Type: application/json.

{
"id": "f1d2c3b4-0000-4a1e-8f3c-2d6b5a9e1c40",
"type": "case.completed",
"apiVersion": "2026-06-05",
"occurredAt": "2026-06-05T12:34:56Z",
"data": {
"caseId": "7c2f1e4a-9b0d-4a1e-8f3c-2d6b5a9e1c40",
"fileName": "document.pdf",
"jobStatus": "completed"
}
}
ChampTypeNotes
idUUIDID de l’événement. Utilisez-le comme clé d’idempotence (voir ci-dessous).
typestringL’un des types d’événement ci-dessus.
apiVersionstringVersion du contrat (2026-06-05). Épinglez-la pour détecter les changements.
occurredAtISO-8601Date de création de l’événement ; stable d’une tentative à l’autre.
data.caseIdUUIDLe cas concerné par cet événement.
data.fileNamestringLe nom du fichier.
data.jobStatusstringStatut brut de la tâche, p. ex. completed, failed, canceled, quota_exceeded.

Les champs nuls sont omis du JSON.

En-têteExempleObjet
X-Accessful-Signaturet=1749126896,v1=9f86d0…Signature HMAC — à vérifier
X-Accessful-Webhook-Timestamp1749126896Secondes Unix ; identique au t= ci-dessus
X-Accessful-Event-Idf1d2c3b4-…Égale id ; clé d’idempotence
X-Accessful-Event-Typecase.completedRoutage sans analyser le corps
X-Accessful-Case-Id7c2f1e4a-…L’ID du cas
X-Accessful-Delivery-Attempt1Compteur de tentatives, à partir de 1
X-Signaturen4bQgY…legacy HMAC base64 sur le corps uniquement

L’en-tête X-Accessful-Signature a la forme t=<unix>,v1=<hex>. Recalculez-la et comparez en temps constant :

  1. Lisez t et v1 dans l’en-tête.
  2. Calculez HMAC-SHA256(secret, "<t>.<corps brut>") et encodez-le en hexadécimal. La chaîne signée est l’horodatage, un point littéral, puis le corps brut exact de la requête — vérifiez avant l’analyse JSON.
  3. Comparez en temps constant avec v1.
  4. Éventuellement, rejetez si t date de plus de quelques minutes (protection contre le rejeu).
import crypto from 'node:crypto';
// `rawBody` doit correspondre aux octets exacts reçus (p. ex. express.raw()).
function verify(rawBody, signatureHeader, secret) {
const parts = Object.fromEntries(signatureHeader.split(',').map((p) => p.split('=')));
const expected = crypto
.createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex');
const valid = crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300; // 5 min
return valid && fresh;
}
  • Succès = toute réponse 2xx dans le délai imparti (5 s pour se connecter, 10 s pour répondre). Répondez vite et effectuez votre travail de manière asynchrone.
  • Échec (non-2xx, délai dépassé ou erreur de connexion) est réessayé jusqu’à 10 tentatives avec un backoff exponentiel et du jitter — environ 10s → 30s → 1,5m → 4,5m → 13,5m → 40m → 2h, puis plafonné à 6h, moins jusqu’à 20 % de jitter. La fenêtre complète s’étend sur plusieurs heures.
  • Après 10 tentatives échouées, l’événement est abandonné. Contactez le support pour une nouvelle livraison.
  • Idempotence : le même événement peut arriver plus d’une fois (p. ex. une nouvelle tentative après que votre endpoint a déjà réussi). Dédupliquez sur X-Accessful-Event-Id — il est stable à chaque tentative.