Développement Zoho
Webhooks et notifications Zoho CRM : pourquoi ils s'arrêtent après 7 jours (et comment les renouveler)
Les notifications de l'API Zoho CRM expirent au plus tard après une semaine. Pourquoi, comment les renouveler automatiquement et fiabiliser la réception.
L'essentiel
Vos mises à jour Zoho CRM cessent d'arriver au bout de quelques jours, sans aucun message d'erreur ? Si votre intégration repose sur l'API de notifications (actions/watch), c'est le comportement prévu : un abonnement expire au plus tard une semaine après son activation. Pire, une durée demandée trop longue, ou oubliée, est ramenée à une heure.
La solution tient en deux pièces : une tâche planifiée qui prolonge chaque abonnement avant son expiration, et un récepteur qui vérifie, journalise et dédoublonne chaque notification.
En bref
- Durée maximale d'un abonnement aux notifications : une semaine.
- Sans date d'expiration, ou avec une date au-delà d'une semaine : une heure seulement.
- Le renouvellement se fait en
PATCHsuractions/watch, en précisant toujours la nouvelle date. - Les webhooks de workflow, eux, n'expirent pas, mais ils ne retentent qu'une fois en cas d'échec.
- Aucun e-mail ne vous prévient quand une intégration s'arrête : la surveillance est à votre charge.
Webhook de workflow ou notification d'API : deux mécanismes différents
On parle de « webhook Zoho » pour deux choses qui ne fonctionnent pas du tout pareil. Identifiez d'abord lequel vous utilisez.
| Webhook de workflow | Notification d'API | |
|---|---|---|
| Mise en place | Dans l'interface : Configuration, Automatisation, Actions, Webhooks | Par un appel d'API sur actions/watch |
| Déclencheur | Les critères d'une règle de workflow | Création, modification ou suppression dans un module, ou sur certains champs |
| Contenu envoyé | Les champs que vous choisissez, en formulaire ou en texte brut | Les identifiants des enregistrements, et en option les valeurs modifiées |
| Expiration | Aucune | Une semaine au maximum |
| Volume | 50 000 à 1 000 000 appels par jour selon l'édition | Pas de quota d'envoi documenté |
Les webhooks de workflow ont leurs propres limites (Zoho) :
- 6 webhooks au plus par règle, dont 1 immédiat et 5 différés ;
- 25 paramètres de module et 10 paramètres personnalisés en formulaire, ou 15 000 caractères en texte brut ;
- une seule relance en cas d'échec, 15 minutes après, puis plus rien pour ce déclenchement ;
- un plafond quotidien : en Enterprise, 500 000 appels par jour ou 500 par utilisateur, la plus basse des deux valeurs ;
- les ports 80 et 443 uniquement.
C'est l'API de notifications qui pose le problème d'expiration. C'est pourtant elle qu'on choisit pour une vraie synchronisation : elle couvre toutes les modifications d'un module, pas seulement celles qui remplissent les critères d'une règle.
Pourquoi les notifications s'arrêtent
La règle tient en une phrase de la documentation de Zoho : la date d'expiration d'un abonnement peut aller jusqu'à une semaine après son activation, et si elle n'est pas précisée ou dépasse une semaine, l'abonnement expire au bout d'une heure (Zoho).
Trois scénarios en découlent, du plus courant au plus piégeux :
- L'abonnement a été créé une fois, à la main. Tout fonctionne pendant les tests, puis s'arrête une semaine plus tard. Personne ne fait le lien avec la mise en production.
- La date demandée dépasse une semaine. Un développeur demande trente jours pour être tranquille. Zoho ne renvoie pas d'erreur : il applique une heure. L'intégration s'arrête le jour même.
- Le renouvellement oublie la date. La mise à jour d'un abonnement suit la même règle : sans nouvelle date d'expiration, elle repart sur une heure (Zoho). Le script « de renouvellement » raccourcit alors l'abonnement au lieu de le prolonger.
Dans les trois cas, aucune alerte ne part. La réponse de Zoho contient pourtant la date d'expiration effectivement appliquée, dans channel_expiry : c'est elle qu'il faut lire et contrôler après chaque création ou renouvellement.
Mettre en place le renouvellement automatique
Le principe : une tâche planifiée tourne chaque jour et repousse l'expiration de chaque abonnement à six jours. Si elle saute un ou deux passages, l'abonnement reste vivant.
- Créez une connexion Zoho CRM avec le scope
ZohoCRM.notifications.ALL. - Rangez le jeton de vérification dans une variable de l'organisation, pas dans le code.
- Créez une fonction planifiée quotidienne dans les automatisations du CRM, avec le code ci-dessous.
- Contrôlez la réponse : en cas d'échec, le code recrée l'abonnement et prévient l'administrateur.
// Fonction planifiée quotidienne : prolonge l'abonnement aux notifications de 6 jours.
// Connexion "zoho_crm", scope ZohoCRM.notifications.ALL. Domaine à adapter (.eu, .com...).
// Le décalage horaire ajouté est approximatif : la marge de 6 jours absorbe l'écart.
expiration = zoho.currenttime.addDay(6).toString("yyyy-MM-dd'T'HH:mm:ss") + "+01:00";
jeton = zoho.crm.getOrgVariable("jeton_notifications");
evenements = list();
evenements.add("Leads.create");
evenements.add("Leads.edit");
abonnement = Map();
abonnement.put("channel_id","1000000068001");
abonnement.put("events",evenements);
abonnement.put("notify_url","https://votre-serveur.fr/zoho/notifications");
abonnement.put("token",jeton);
abonnement.put("channel_expiry",expiration);
liste = list();
liste.add(abonnement);
corps = Map();
corps.put("watch",liste);
reponse = invokeurl
[
url :"https://www.zohoapis.eu/crm/v8/actions/watch"
type :PATCH
parameters:corps.toString()
connection:"zoho_crm"
];
info reponse;
statut = "";
if(reponse.containKey("watch"))
{
statut = reponse.get("watch").get(0).get("code");
}
// Abonnement déjà expiré ou supprimé : on le recrée et on prévient l'administrateur
if(statut != "SUCCESS")
{
reponse = invokeurl
[
url :"https://www.zohoapis.eu/crm/v8/actions/watch"
type :POST
parameters:corps.toString()
connection:"zoho_crm"
];
sendmail
[
from :zoho.adminuserid
to :"admin@votre-entreprise.fr"
subject :"Notifications Zoho CRM recréées"
message :reponse.toString()
]
}
Vous préférez gérer le renouvellement depuis votre serveur ? La seule difficulté est la date, qui doit suivre le format ISO 8601 avec son décalage horaire. En PHP, une ligne suffit :
$expiration = (new DateTimeImmutable('+6 days'))->format(DATE_ATOM); // ex. 2026-10-26T22:40:00+03:00
Chaque renouvellement coûte un crédit d'API : un abonnement prolongé chaque jour consomme 30 crédits par mois, une goutte d'eau dans le quota quotidien (limites de l'API Zoho CRM).
Fiabiliser la réception
Un abonnement renouvelé ne sert à rien si le récepteur perd des notifications. Cinq règles suffisent :
- Vérifier l'origine. Chaque notification renvoie le
tokenet lechannel_idque vous avez définis. Rejetez tout appel qui ne les porte pas. - Répondre tout de suite, traiter ensuite. Le récepteur enregistre la notification, répond immédiatement et laisse un traitement en arrière-plan faire le travail. Un traitement long pendant la réponse expose aux dépassements de délai.
- Dédoublonner. Construisez une clé par notification, par exemple canal, enregistrements, opération et
server_time, et ignorez ce qui a déjà été traité. - Demander les valeurs modifiées. Avec
return_affected_field_values, Zoho envoie les champs modifiés et leurs nouvelles valeurs. Vous économisez une lecture d'API par notification. - Filtrer à la source. Une condition portant sur 10 champs au plus limite l'envoi aux changements utiles, par exemple l'étape d'une affaire (Zoho).
Voici ce que Zoho envoie, en version simplifiée d'après sa documentation :
{
"server_time": 1718115953625,
"module": "Leads",
"operation": "update",
"ids": ["5725767000003000010"],
"affected_values": [
{ "record_id": "5725767000003000010", "values": { "Mobile": "123456789" } }
],
"channel_id": "1000000068001",
"token": "TOKEN_FOR_VERIFICATION_OF_1000000068001"
}
Et un récepteur PHP minimal qui applique les règles 1 à 3 :
<?php
// Récepteur minimal : vérifie le jeton, dédoublonne, stocke, répond tout de suite.
// Table MySQL zoho_notifications avec une clé primaire sur la colonne cle.
$jetonAttendu = (string) getenv('ZOHO_NOTIF_TOKEN');
$notif = json_decode(file_get_contents('php://input'), true);
if (!is_array($notif) || !hash_equals($jetonAttendu, (string) ($notif['token'] ?? ''))) {
http_response_code(403);
exit;
}
$cle = sha1(($notif['channel_id'] ?? '') . '|' . implode(',', $notif['ids'] ?? [])
. '|' . ($notif['operation'] ?? '') . '|' . ($notif['server_time'] ?? ''));
$pdo = new PDO(getenv('DB_DSN'), getenv('DB_USER'), getenv('DB_PASS'));
$requete = $pdo->prepare('INSERT IGNORE INTO zoho_notifications (cle, contenu, recu_le) VALUES (?, ?, NOW())');
$requete->execute([$cle, json_encode($notif)]); // une clé déjà vue est ignorée
http_response_code(200); // un traitement en arrière-plan lit ensuite la table
Diagnostiquer une notification qui n'arrive plus
Passez ces contrôles dans l'ordre : les premiers expliquent la grande majorité des pannes.
- ☐ L'abonnement existe-t-il encore ? Un
GETsuractions/watchliste vos canaux et leur date d'expiration (Zoho). - ☐ Sa date d'expiration est-elle dans le futur, et plus loin qu'une heure ?
- ☐ La tâche de renouvellement a-t-elle tourné ces deux derniers jours, et sa réponse indiquait-elle
SUCCESS? - ☐ Les crédits d'API étaient-ils disponibles au moment du renouvellement ? Un quota épuisé bloque aussi cet appel.
- ☐ L'événement est-il bien dans la liste : création, modification, suppression ?
- ☐ La condition sur les champs filtre-t-elle trop ? Une modification d'un champ hors liste ne déclenche rien.
- ☐ L'adresse de réception répond-elle en HTTPS, avec un certificat valide, et rapidement ?
- ☐ Le jeton reçu correspond-il à celui que votre récepteur attend ? Un jeton changé d'un seul côté fait tout rejeter.
- ☐ Pour un webhook de workflow : la règle se déclenche-t-elle, et le plafond quotidien d'appels est-il atteint ? Dans ce cas, Zoho prévient l'administrateur.
Pour ne plus découvrir une panne par hasard, ajoutez une sonde : si aucune notification n'est arrivée depuis plusieurs heures en journée de travail, votre équipe reçoit une alerte.
Faire fiabiliser vos intégrations
Un renouvellement automatique, un récepteur qui dédoublonne et une sonde d'alerte représentent en général une demi-journée à une journée de travail pour un développeur qui connaît l'API. Pour en savoir plus, consultez notre checklist d'audit Zoho CRM.
Vos notifications Zoho s'arrêtent sans prévenir ?
SquadNovia met en place le renouvellement, sécurise votre récepteur et ajoute l'alerte qui vous évitera la prochaine panne silencieuse. Une banque de 10 heures couvre la plupart des cas.
Questions fréquentes
Pourquoi mon abonnement aux notifications Zoho CRM expire-t-il au bout d'une heure ?
Parce que la date d'expiration n'a pas été précisée, ou qu'elle dépassait une semaine. Dans les deux cas, Zoho applique une heure par défaut, sans renvoyer d'erreur.
Peut-on créer un abonnement qui n'expire jamais ?
Non. Une semaine est le maximum. Seul un renouvellement automatique garantit la continuité.
Les webhooks de workflow expirent-ils aussi ?
Non. En revanche, ils ne retentent qu'une fois en cas d'échec, 15 minutes après, et s'arrêtent quand le plafond quotidien de votre édition est atteint.
Combien coûte le renouvellement en crédits d'API ?
Un crédit par appel. Un renouvellement quotidien consomme une trentaine de crédits par mois.
Webhook de workflow ou notification d'API : lequel choisir ?
Le webhook de workflow pour prévenir un outil quand un événement précis survient, par exemple une affaire gagnée. La notification d'API pour synchroniser toutes les modifications d'un module avec un autre système.
Peut-on limiter les notifications à certains champs ?
Oui. Une condition peut porter sur 10 champs au plus, regroupés avec « et » ou « ou » : la modification d'un autre champ ne déclenche alors aucune notification.
Sources
Pages consultées le 20 octobre 2026.