Zapier pour l'automatisation métier
Dans un contexte d'entreprise comme chez ORPI, l'automatisation des processus métier via les APIs est essentielle pour gagner en efficacité.
Zapier est une plateforme d'automatisation sans code qui relie des milliers d'applications SaaS entre elles. Son intérêt pour une équipe technique est double : les équipes métier construisent elles-mêmes leurs automatisations, et les développeurs n'ont qu'à exposer quelques points d'entrée propres et sécurisés dans leurs applications. Cet article montre comment préparer une application Symfony à dialoguer avec Zapier dans les deux sens.
Les notions de base
- Zap : un scénario d'automatisation, composé d'un déclencheur et d'une ou plusieurs actions.
- Trigger (déclencheur) : l'événement qui lance le Zap, par exemple un nouveau prospect ou un formulaire soumis.
- Action : ce que fait le Zap ensuite, par exemple créer une ligne dans un tableur, envoyer un message Slack ou appeler votre API.
- Task : chaque action exécutée avec succès compte comme une tâche, et c'est sur ce volume que repose la facturation.
Un déclencheur fonctionne de deux façons : par polling, où Zapier interroge régulièrement une URL pour détecter les nouveaux éléments, ou de façon instantanée, où votre application prévient Zapier par un webhook dès que l'événement survient.
Cas d'usage courants
- Synchronisation CRM vers base de données interne
- Notification Slack sur événements métier
- Génération automatique de rapports
- Intégration de formulaires web avec le SI
Le point commun de ces cas : des flux simples, à volume modéré, qui relient des outils existants. C'est là que Zapier est le plus rentable, car il évite de développer et de maintenir un connecteur pour chaque outil.
Créer un webhook personnalisé
Premier sens : Zapier envoie des données à votre application. Dans le Zap, l'action « Webhooks by Zapier » en mode POST envoie un JSON vers votre endpoint, avec des en-têtes que vous définissez, dont un jeton secret :
// Endpoint Symfony pour recevoir les webhooks Zapier
#[Route('/api/webhook/zapier', methods: ['POST'])]
class ZapierWebhookController extends AbstractController
{
public function __construct(
#[Autowire(env: 'ZAPIER_TOKEN')]
private readonly string $zapierToken,
) {}
public function __invoke(
Request $request,
MessageBusInterface $bus,
): JsonResponse {
// Valider le token
$token = (string) $request->headers->get('X-Zapier-Token', '');
if (!hash_equals($this->zapierToken, $token)) {
return $this->json(['error' => 'Unauthorized'], 401);
}
$data = json_decode($request->getContent(), true);
if (!is_array($data)) {
return $this->json(['error' => 'Invalid JSON'], 400);
}
// Dispatcher le traitement
$bus->dispatch(new ProcessZapierDataMessage($data));
return $this->json(['status' => 'received']);
}
}
Plusieurs détails comptent dans ce contrôleur :
- le jeton est lu depuis une variable d'environnement grâce à l'attribut
#[Autowire(env: ...)](Symfony 6.3 et plus), jamais écrit en dur dans le code ; hash_equals()compare les chaînes en temps constant, ce qui évite de laisser deviner le jeton caractère par caractère ;- la vérification du jeton a lieu avant toute lecture du contenu, et un JSON invalide est rejeté avec une erreur 400 ;
- le traitement réel part dans Messenger : le contrôleur répond en quelques millisecondes, ce qui évite les délais d'expiration côté Zapier.
Le secret se stocke comme les autres secrets de l'application, par exemple avec le coffre-fort de Symfony :
php bin/console secrets:set ZAPIER_TOKEN
# Générer une valeur robuste
openssl rand -hex 32
API pour Zapier Triggers
Second sens : votre application fournit des données à Zapier. Pour un déclencheur par polling, construit dans une intégration privée sur la plateforme développeur de Zapier, il suffit d'exposer un endpoint qui renvoie les éléments les plus récents :
#[Route('/api/zapier/new-leads', methods: ['GET'])]
public function newLeads(LeadRepository $repo): JsonResponse
{
$leads = $repo->findRecent(limit: 50);
return $this->json(array_map(fn(Lead $l) => [
'id' => $l->getId(),
'name' => $l->getName(),
'email' => $l->getEmail(),
'created_at' => $l->getCreatedAt()->format('c'),
], $leads));
}
Zapier attend un tableau JSON d'objets, du plus récent au plus ancien, chacun doté d'un champ id unique. Il mémorise les identifiants déjà vus et ne déclenche le Zap que pour les nouveaux : c'est la déduplication. Deux conséquences pratiques : l'id d'un élément ne doit jamais changer, et findRecent() doit trier par date de création décroissante. Protégez aussi cet endpoint, par exemple avec une clé d'API transmise dans un en-tête et vérifiée par le composant Security.
Déclencheurs instantanés
Le polling introduit un délai, qui dépend de l'abonnement Zapier. Pour une réaction immédiate, l'application peut pousser l'événement vers l'URL fournie par le déclencheur « Catch Hook » de Webhooks by Zapier. Faites-le depuis un handler Messenger, pour qu'une indisponibilité de Zapier ne ralentisse jamais vos utilisateurs :
#[AsMessageHandler]
final class NotifyZapierHandler
{
public function __construct(
private readonly HttpClientInterface $httpClient,
#[Autowire(env: 'ZAPIER_HOOK_URL')]
private readonly string $zapierHookUrl,
) {}
public function __invoke(LeadCreatedMessage $message): void
{
$response = $this->httpClient->request('POST', $this->zapierHookUrl, [
'json' => [
'id' => $message->leadId,
'name' => $message->name,
'email' => $message->email,
],
'timeout' => 10,
]);
// Lève une exception si le statut n'est pas 2xx : Messenger réessaiera
$response->getContent();
}
}
Si Zapier est momentanément indisponible, l'exception déclenche la stratégie de réessai de Messenger, puis le transport d'échec : aucun événement n'est perdu. Pour une intégration publique, Zapier propose aussi les REST Hooks : Zapier enregistre lui-même son URL auprès de votre API à l'activation d'un Zap et la supprime à sa désactivation.
Pièges courants
- Doublons : un webhook peut être rejoué, par Zapier ou par un utilisateur qui relance une exécution. Rendez le traitement idempotent, par exemple en stockant l'identifiant de l'événement reçu.
- Données personnelles : chaque champ envoyé transite par les serveurs de Zapier. N'envoyez que le strict nécessaire et vérifiez la conformité RGPD du flux avec votre DPO.
- Logique métier dans Zapier : des filtres et des chemins complexes dans un Zap deviennent vite impossibles à tester et à versionner. Gardez les règles métier dans l'application.
- Coût : la facturation à la tâche peut grimper vite sur des flux à fort volume.
Quand ne pas utiliser Zapier
Pour des milliers d'événements par heure, un flux critique pour le chiffre d'affaires ou une transformation de données complexe, une intégration développée directement entre les deux APIs reste plus fiable, plus économique et plus facile à surveiller. Zapier excelle pour les automatisations internes, les prototypes et les flux que les équipes métier doivent pouvoir faire évoluer seules.
Bonnes pratiques
- Sécuriser les webhooks avec des tokens
- Logger toutes les interactions pour le débogage
- Utiliser des files d'attente pour le traitement asynchrone
- Documenter les APIs avec OpenAPI pour l'intégration Zapier
- Limiter le débit des endpoints publics avec le composant RateLimiter de Symfony
- Répondre vite, avec un code 2xx, et traiter ensuite
Avec quelques endpoints bien conçus, sécurisés et asynchrones, votre application devient une brique que les équipes métier peuvent brancher à leurs outils sans solliciter les développeurs pour chaque nouveau besoin.