Skip to content

Webhooks ​

Les webhooks permettent à une application tierce d'être notifiée en temps réel des évènements qui surviennent dans atimeüs, sans avoir à interroger l'API en continu.

Principe ​

Un webhook associe une URL à un ou plusieurs déclencheurs. À chaque occurrence d'un déclencheur souscrit, atimeüs envoie une requête POST en application/json; charset=utf-8 vers l'URL configurée.

http
POST /mon-endpoint HTTP/1.1
Host: exemple.com
Content-Type: application/json; charset=utf-8
X-Atimeus-Webhook-Date: 2026-09-16T13:42:07
X-Atimeus-Webhook-Signature: hV2mQ0d1v3Yb8Kx6Lp9Tn4Rj7Ws5Cz1Ae0Uf2Gh3Io=

{"trigger":"project.created","date":"2026-09-16T13:42:05","data":{...}}

Créer un webhook ​

Depuis l'interface ​

La gestion des webhooks s'effectue depuis l'écran : https://<instance>/admin/settings/webhooks

L'accès à cet écran nécessite le droit Webhooks.

Le formulaire de création comporte les champs suivants :

ChampDescription
NomLibellé du webhook, utilisé uniquement pour le retrouver dans la liste.
URLAdresse appelée lors de chaque envoi.
SecretClé utilisée pour signer les envois. Optionnel.
Déclencheur(s)Un ou plusieurs déclencheurs parmi la liste ci-dessous.

Un webhook est créé actif. La liste des webhooks permet ensuite de l'activer ou de le désactiver via la colonne Actif ?, et affiche dans la colonne Dernier appel le code HTTP retourné lors du dernier envoi.

Depuis l'API ​

Les webhooks peuvent également être pilotés par l'API, pour les besoins d'automatisation :

RequêteDescription
GET restapi/webhooks/triggersListe des déclencheurs disponibles.
GET restapi/webhooks/views/view-allListe des webhooks configurés.
GET restapi/webhooks/{id}Détail d'un webhook.
POST restapi/webhooksCréation d'un webhook.
PATCH restapi/webhooks/{id}Mise à jour d'un webhook (voir Mise à jour d'une entité).
DELETE restapi/webhooks/{id}Suppression d'un webhook.
GET restapi/webhooks/{id}/lastrunRésultat du dernier envoi du webhook.

Le détail des schémas est disponible dans la Référence de l'API.

Deux points d'attention :

  • les déclencheurs sont stockés dans une chaîne unique, séparés par des points-virgules : project.created;project.synced ;
  • le champ secret n'est jamais renvoyé en lecture par l'API. Il peut uniquement être réécrit.

Déclencheurs disponibles ​

La colonne « Contenu envoyé » indique laquelle des cinq formes de corps décrites dans la section Format de la requête est utilisée.

DéclencheurDescriptionContenu envoyé
project.createdUn projet a été créé.data
project.updatedUn projet a été modifié.from / to
project.deletedUn projet a été supprimé.id
project.syncedUn projet a été synchronisé.id
project-task.createdUne tâche de projet a été créée.data
project-task.updatedUne tâche de projet a été modifiée.from / to
project-task.deletedUne tâche de projet a été supprimée.id
contract.createdUn contrat a été créé.data
contract.updatedUn contrat a été modifié.from / to
contract.deletedUn contrat a été supprimé.id
invoice.createdUne facture a été créée.data
invoice.updatedUne facture a été modifiée.from / to
invoice.deletedUne facture a été supprimée.id
invoice.validatedUne facture a été validée.id
employee.createdUn collaborateur a été créé.data
employee.updatedUn collaborateur a été modifié.from / to
employee.deletedUn collaborateur a été supprimé.id
customer.createdUn client a été créé.data
customer.updatedUn client a été modifié.from / to
customer.deletedUn client a été supprimé.id
subcontractor.createdUn sous-traitant a été créé.data
subcontractor.updatedUn sous-traitant a été modifié.from / to
subcontractor.deletedUn sous-traitant a été supprimé.id
user-task.createdUne tâche utilisateur a été créée.data
user-task.updatedUne tâche utilisateur a été modifiée.from / to
user-task.deletedUne tâche utilisateur a été supprimée.id
quotes.validatedUn devis a été validé.id
opportunity.createdUne opportunité a été créée.data
opportunity.updatedUne opportunité a été modifiée.from / to
opportunity.deletedUne opportunité a été supprimée.id
opportunity.wonUne opportunité est passée au statut gagné.data
opportunity.lostUne opportunité est passée au statut perdu.data
contact.createdUn contact a été créé.data
contact.updatedUn contact a été modifié.from / to
contact.deletedUn contact a été supprimé.id
application.createdUne candidature a été créée.data
application.updatedUne candidature a été modifiée.from / to
application.deletedUne candidature a été supprimée.id
application.wonUne candidature est passée au statut gagné.data
application.lostUne candidature est passée au statut perdu.data
candidate.createdUn candidat a été créé.data
candidate.updatedUn candidat a été modifié.from / to
candidate.deletedUn candidat a été supprimé.id
month.closedUn mois a été clôturé.(aucun)
timesheet.completedUn collaborateur a complété son CRA.période de CRA
timesheet.validatedUn CRA a été validé par le manager.période de CRA
timesheet.closedUn CRA a été clôturé.période de CRA
timesheet.unlockedUn CRA a été déverrouillé.période de CRA

Format de la requête ​

En-têtes ​

En-têteDescription
X-Atimeus-Webhook-DateDate d'envoi UTC, au format yyyy-MM-ddTHH:mm:ss. Elle change à chaque nouvelle tentative.
X-Atimeus-Webhook-SignatureSignature HMAC-SHA256 du message, encodée en Base64. Présente uniquement si un secret est défini sur le webhook.

Enveloppe commune ​

Quelle que soit sa forme, le corps contient au minimum les propriétés trigger et date :

  • trigger : le déclencheur à l'origine de l'envoi ;
  • date : la date UTC de l'évènement, au format yyyy-MM-ddTHH:mm:ss, sans millisecondes ni suffixe de fuseau. Contrairement à l'en-tête X-Atimeus-Webhook-Date, elle reste identique entre les tentatives d'un même évènement.

Les propriétés sont sérialisées en camelCase.

L'objet contenu dans data, from et to est identique à la réponse de lecture REST de l'entité correspondante — par exemple GET restapi/projects/{id} pour project.created — champs personnalisés du tenant inclus. Le détail des champs est disponible dans la Référence de l'API.

Forme data ​

L'enveloppe porte une propriété data contenant l'entité complète. Cette forme est utilisée par les déclencheurs *.created, ainsi que par opportunity.won, opportunity.lost, application.won et application.lost.

json
{
  "trigger": "project.created",
  "date": "2026-09-16T13:42:05",
  "data": {
    "id": "b1f9e0c4-3a7d-4e21-9f55-0c2a8d61b743",
    "name": "Refonte du portail client",
    "createDate": "2026-09-16T13:42:05",
    ... // l'ensemble des champs retournés par GET restapi/projects/{id}
  }
}

Forme from / to ​

L'enveloppe porte deux propriétés : from, l'état antérieur de l'entité, et to, son état courant. Cette forme est utilisée par les déclencheurs *.updated.

json
{
  "trigger": "project.updated",
  "date": "2026-09-16T14:05:11",
  "from": {
    "id": "b1f9e0c4-3a7d-4e21-9f55-0c2a8d61b743",
    "name": "Refonte du portail client",
    ...
  },
  "to": {
    "id": "b1f9e0c4-3a7d-4e21-9f55-0c2a8d61b743",
    "name": "Refonte du portail client - phase 2",
    ...
  }
}

Lorsque l'état antérieur n'a pas pu être reconstitué, seule la propriété to est présente.

Forme id ​

L'enveloppe porte une unique propriété id contenant l'identifiant de l'entité concernée. Cette forme est utilisée par les déclencheurs *.deleted, ainsi que par project.synced, invoice.validated et quotes.validated.

json
{
  "trigger": "project.deleted",
  "date": "2026-09-16T14:22:48",
  "id": "b1f9e0c4-3a7d-4e21-9f55-0c2a8d61b743"
}

Forme période de CRA ​

L'enveloppe porte quatre propriétés identifiant le CRA concerné : id, employeeId, year et month. Cette forme est utilisée par les déclencheurs timesheet.completed, timesheet.validated, timesheet.closed et timesheet.unlocked.

json
{
  "trigger": "timesheet.validated",
  "date": "2026-09-16T13:42:05",
  "id": "7c3e9a51-4d82-4f0b-8a16-5b9d2e7c41f8",
  "employeeId": "b1f9e0c4-3a7d-4e21-9f55-0c2a8d61b743",
  "year": 2026,
  "month": 9
}

Le corps ne contient volontairement aucune donnée personnelle : ni le nom du collaborateur, ni son manager, ni sa société. Le consommateur qui a besoin du détail rappelle les vues de CRA de l'API, soit sur l'id de la période, soit en filtrant sur le triplet collaborateur / année / mois.

Si la période a été supprimée entre l'évènement et son envoi, le corps retombe sur la forme id et porte le même identifiant de période que les évènements précédents.

Forme minimale ​

Aucune propriété au-delà de trigger et date.

json
{
  "trigger": "month.closed",
  "date": "2026-10-01T02:00:00"
}

Secret et signature ​

Le secret est saisi librement lors de la création du webhook. Il est optionnel, mais sans secret aucune signature n'est émise : l'en-tête X-Atimeus-Webhook-Signature est alors absent et l'authenticité de l'appel ne peut pas être vérifiée.

Pour vérifier une signature :

  1. calculer le HMAC-SHA256 en utilisant le secret comme clé, sur la concaténation de la valeur de l'en-tête X-Atimeus-Webhook-Date, d'un caractère deux-points, puis du corps brut de la requête ;
  2. encoder le résultat en Base64 ;
  3. comparer la valeur obtenue à l'en-tête X-Atimeus-Webhook-Signature.

La vérification doit porter sur le corps brut reçu, avant toute désérialisation ou reformatage : une simple réindentation du JSON invalide la signature.

Trois pièges à éviter :

  • la date utilisée est celle de l'en-tête X-Atimeus-Webhook-Date, et non la propriété date du corps — les deux diffèrent dès la première nouvelle tentative ;
  • le séparateur entre la date et le corps est un deux-points ;
  • l'encodage de sortie est le Base64, et non l'hexadécimal, et la valeur ne comporte aucun préfixe de type sha256=.

Les webhooks dont l'URL cible Make.com font exception : le secret y est transmis via un en-tête d'authentification dédié, x-make-apikey, à la place de la signature HMAC.

Livraison et nouvelles tentatives ​

Un envoi est considéré comme réussi lorsque l'endpoint répond un code 2xx. Tout autre code, comme toute absence de réponse, est traité comme un échec.

En cas d'échec, l'envoi est retenté jusqu'à 5 tentatives au total, avec un délai exponentiel entre chacune.

Au-delà de la cinquième tentative, l'évènement n'est plus retenté.

Enfin, un même évènement peut être reçu plusieurs fois, notamment lorsqu'une tentative a abouti côté atimeüs sans que la réponse soit parvenue. Le consommateur doit donc tolérer les doublons, par exemple en rendant son traitement idempotent.